Read in the labelled object Run the correlation comparison between the total scRNA per FACS pop and the AB levels Calculate the proportion of the cell types from the orginal labels UMAP of the cell POPS merged UMAP of the subtypes labelled
library(Seurat)
Attaching SeuratObject
Attaching sp
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library('reshape')
Attaching package: ‘reshape’
The following object is masked from ‘package:dplyr’:
rename
library("ggplot2")
Read in the lableled object single cell sequencing
saveRDS(seu.sc,,paste(pathway, "CombinedLabeledMarkers14102022.RDS"))
Error in saveRDS(seu.sc, , paste(pathway, "CombinedLabeledMarkers14102022.RDS")) :
'file' must be non-empty string
NA
Read in the Flow Cytometry data
output_path = "/Users/rhalenathomas/Documents/Data/FlowCytometry/PhenoID/Analysis/PaperFigures/PostSortGatingPops/"
seu.fc <- readRDS(paste(output_path,"june10postSort.seu.RDS", sep = ""))
unique(seu.fc$GatedPop)
[1] Astrocytes RadialGlia Neurons1 Neurons2
Levels: Astrocytes RadialGlia Neurons1 Neurons2
Marker list
marker.ab <- c("CD24","CD56","CD29","CD15","CD184","CD133","CD71","CD44","GLAST","AQP4","HepaCAM", "CD140a","O4")
marker.genes <-c("CD24","NCAM1","ITGB1","FUT4","CXCR4","PROM1","TFRC","CD44","SLC1A3","AQP4","HEPACAM", "PDGFRA","NKX6-2")
Make the expression matrixes
seu.sc <- ScaleData(object = seu.sc, features = rownames(seu.sc))
Centering and scaling data matrix
|
| | 0%
|
|=== | 3%
|
|===== | 6%
|
|======== | 9%
|
|========== | 12%
|
|============= | 15%
|
|================ | 18%
|
|================== | 21%
|
|===================== | 24%
|
|======================== | 26%
|
|========================== | 29%
|
|============================= | 32%
|
|=============================== | 35%
|
|================================== | 38%
|
|===================================== | 41%
|
|======================================= | 44%
|
|========================================== | 47%
|
|============================================ | 50%
|
|=============================================== | 53%
|
|================================================== | 56%
|
|==================================================== | 59%
|
|======================================================= | 62%
|
|========================================================== | 65%
|
|============================================================ | 68%
|
|=============================================================== | 71%
|
|================================================================= | 74%
|
|==================================================================== | 76%
|
|======================================================================= | 79%
|
|========================================================================= | 82%
|
|============================================================================ | 85%
|
|=============================================================================== | 88%
|
|================================================================================= | 91%
|
|==================================================================================== | 94%
|
|====================================================================================== | 97%
|
|=========================================================================================| 100%
Calculate correlation between two matrixes
df.cor
Astrocytes RadialGlia Neurons1 Neurons2
Astrocytes 0.5553328 0.1522878 -0.4517431 -0.18064326
RadialGlia 0.1305815 0.4451073 -0.3314321 0.05559489
Neurons1 -0.4098105 -0.3016957 0.4534910 0.05175022
Neurons2 -0.4858683 -0.1624758 0.3770386 0.23752196
write.csv(df.cor, paste(output_path,"CorrelationsFCscRNAseq.csv"))
Plot the heatmap Figure 6A
# need to melt the matrix
longData<- melt(df.cor)
Warning in type.convert.default(X[[i]], ...) :
'as.is' should be specified by the caller; using TRUE
Warning in type.convert.default(X[[i]], ...) :
'as.is' should be specified by the caller; using TRUE
head(longData)
colnames(longData) <- c("FC","scRNA","R2")
ggplot(longData, aes(x=scRNA,y=FC, fill =R2)) + geom_tile() +
scale_fill_gradient2(low = "#075AFF",
mid = "#FFFFCC",
high = "#FF0000") +
guides(fill = guide_colourbar(label = TRUE,
ticks = FALSE)) + theme_bw() +
coord_fixed() +scale_x_discrete(expand=c(0,0))+
scale_y_discrete(expand=c(0,0))+ theme(text = element_text(size=16, colour = "black"),
axis.text.x = element_text(size = 18, colour = "black", angle = 90), axis.text.y = element_text(size= 18, colour = "black")) + xlab('scRNAseq') + ylab('Flow Cytometry')
output_path <- "/Users/rhalenathomas/Documents/Projects_Papers/PhenoID/ForFigures/scRNA/"
pdf(paste(output_path,"FC_scRNA_correlationOct16.pdf"), width = 8, height = 5)
ggplot(longData, aes(x=scRNA,y=FC, fill =R2)) + geom_tile() +
scale_fill_gradient2(low = "#075AFF",
mid = "#FFFFCC",
high = "#FF0000", midpoint = 0, limit = c(-0.5,0.5)) +
guides(fill = guide_colourbar(label = TRUE,
ticks = FALSE)) + theme_bw() +
coord_fixed() +scale_x_discrete(expand=c(0,0)) +
scale_y_discrete(expand=c(0,0)) +
theme(text = element_text(size=16, colour = "black"),
axis.text.x = element_text(size = 16, colour = "black", angle = 90), axis.text.y = element_text(size= 16, colour = "black")) + xlab('scRNAseq') + ylab('Flow Cytometry')
dev.off()
quartz_off_screen
2

Compare proportions of cells in each FACS pop - Figure 6B

Make a table of cell types
library(stringr)
library(reshape)
# for original cell types
df.r <- reshape(df, idvar = "Var2", timevar = "Var1", direction = "wide")
dat1 <- df.r
dat1[] <- lapply(dat1[], function(x){
# Check if the column is numeric
if (is.numeric(x)){
return(x/sum(x)*100)
} else{
return(x)
}
})
dat1
write.csv(dat1, paste(output_path,"proportionofCelltypesin4pops.csv"))
### for new main cell types
df.r <- reshape(df.3, idvar = "Var2", timevar = "Var1", direction = "wide")
Error in reshape(df.3, idvar = "Var2", timevar = "Var1", direction = "wide") :
object 'df.3' not found
UMAP with original idents to show overlap (or lack there of) Figure 6C
# Figure 6 C
# UMAP with the 4 orig.idents
sample.order <- c("Astrocytes","RadialGlia","Neurons1","Neurons2")
sample.order <- rev(sample.order)
# colour order to match cell type order
clust.colours <- c("royalblue", "indianred2","palegreen2","springgreen4")
Idents(seu.sc) <- 'orig.ident'
DimPlot(seu.sc, order = sample.order, cols = clust.colours, shuffle = TRUE, raster=FALSE, pt.size = 0.1, label = FALSE)
output_path <- "/Users/rhalenathomas/Documents/Projects_Papers/PhenoID/ForFigures/scRNA/"
### Figure 6C
pdf(paste(output_path,"UMAPscRNAseqMerge4Oct16.pdf"),width = 7, height = 4)
DimPlot(seu.sc, order = sample.order, cols = clust.colours, shuffle = TRUE, raster=FALSE, pt.size = 0.1, label = FALSE, label.size = 6) +
theme(legend.text = element_text(size=16), axis.title.y = element_text(size=16),
axis.title.x = element_text(size=16), axis.text.y = element_text(size =16),
axis.text.x = element_text(size =16))
dev.off()
quartz_off_screen
2

## Figure S23 panel
cell.order <- c("Astrocytes","Endothelial","Glia","NPC","Neurons","Other","Radial Glia")
cell.order <- rev(cell.order)
# colour order to match cell type order
clust.colours <- c("chocolate1","deepskyblue","steelblue4","red2","mediumpurple3","burlywood3",
"pink2")
Idents(seu.sc) <- 'Cell_Types'
# designated the order of the splits factor
seu.sc$orig.ident <- factor(x = seu.sc$orig.ident, levels = c("Astrocytes","RadialGlia","Neurons1","Neurons2"))
DimPlot(seu.sc, order = cell.order, cols = clust.colours, shuffle = TRUE, raster=FALSE, pt.size = 0.1, label = FALSE, split.by = 'orig.ident', ncol = 2)
pdf(paste(output_path,"UMAP_merge_splitbyorigidentOct16.pdf"),width = 12, height = 7.5)
DimPlot(seu.sc, order = cell.order, cols = clust.colours, shuffle = TRUE, raster=FALSE, pt.size = 0.1, label = FALSE, split.by = 'orig.ident', label.size = 6, ncol = 2) +
theme(legend.text = element_text(size=16), axis.title.y = element_text(size=16),
axis.title.x = element_text(size=16), axis.text.y = element_text(size =16),
axis.text.x = element_text(size =16))
dev.off()
quartz_off_screen
2

# also plot one not split to see the whole thing
#pdf(paste(output_path,"UMAP_merge_CellTypesOct16.pdf"),width = 6.7, height = 4.1)
DimPlot(seu.sc, order = cell.order, cols = clust.colours, shuffle = TRUE, raster=FALSE, pt.size = 0.1, label = FALSE, label.size = 6) +
theme(legend.text = element_text(size=16), axis.title.y = element_text(size=16),
axis.title.x = element_text(size=16), axis.text.y = element_text(size =16),
axis.text.x = element_text(size =16))

#dev.off()
Figure 6D - UMAP with subgroups
pdf(paste(output_path,"UMAP_CellSubtypeMarkersLablesOct16.pdf"),width = 12, height = 5)
DimPlot(seu.sc, order = sample.order, cols = clust.colours, shuffle = TRUE, raster=FALSE, pt.size = 0.25, label = TRUE, repel = TRUE)
dev.off()
null device
1
Make a heatmap


Heatmap or Dotplot Save pdf

save the heatmap Change the colours
pdf(paste(output_path,"HeatMapsubtypesOct17.pdf",sep = ""),width = 11, height = 5)
DoHeatmap(seu.sc, features = feature_list, group.by = 'Cell_Subtype_Markers', group.colors = clust.colours, disp.max = 2, disp.min = -1.5,
angle = 90) + scale_fill_gradientn(colors = c("#154c79", "#eeeee4", "#e28743")) +
theme(axis.text.y = element_text(size = 16))
Scale for 'fill' is already present. Adding another scale for 'fill', which will replace the
existing scale.
dev.off()
null device
1
Subtype markers
Idents(seu.sc) <- 'Cell_Subtypes'
neurons <- subset(seu.sc, idents = c("Neurons1","Neurons2","Neurons3","Neurons4",
"Neurons5","Neurons6","Neurons7"))
Idents(neurons) <- 'Cell_Subtype_Markers'
pdf(paste(output_path,"UMAP_NeuronsOct17.pdf",sep = ""),width = 7, height = 4)
DimPlot(neurons) + theme(text = element_text(size=16, colour = "black"))
dev.off()
null device
1
Idents(seu.sc) <- 'Cell_Subtypes'
neurons.da <- subset(seu.sc, idents = c("DANeurons1","DANeurons2","DANeurons3"))
Idents(neurons.da) <- 'Cell_Subtype_Markers'
pdf(paste(output_path,"UMAP_DANeuronsOct17.pdf",sep = ""),width = 7, height = 4)
DimPlot(neurons.da)+ theme(text = element_text(size=16, colour = "black"))
dev.off()
null device
1
Idents(seu.sc) <- 'Cell_Subtypes'
astro <- subset(seu.sc, idents = c("Astrocytes1","Astrocytes2","Astrocytes3"))
Idents(astro) <- 'Cell_Subtype_Markers'
pdf(paste(output_path,"UMAP_AstroOct17.pdf",sep = ""),width = 7, height = 4)
DimPlot(astro)+ theme(text = element_text(size=16, colour = "black"))
dev.off()
null device
1
Idents(seu.sc) <- 'Cell_Subtypes'
rg <- subset(seu.sc, idents = c("RadialGlia1","RadialGlia2","RadialGlia3","RadialGlia4",
"RadialGlia5","RadialGlia6"))
Idents(rg) <- 'Cell_Subtype_Markers'
pdf(paste(output_path,"UMAP_RGOct17.pdf",sep = ""),width = 7, height = 4)
DimPlot(rg)+ theme(text = element_text(size=16, colour = "black"))
dev.off()
null device
1
DotPlots of markers in cell type subsets
n.markers <- c("ASCL1","CP","GRIA2","MGP","SPARCL1","TPH1","TFPI2","CD24")
pdf(paste(output_path,"Dotplot_NeuSubMarkersOct17.pdf",sep = ""),width = 7, height = 4)
DotPlot(neurons, features = n.markers) +
theme(text = element_text(size=16, colour = "black"),axis.text.x = element_text(angle = 90))
dev.off()
null device
1
da.markers <- c("RAB3B","TPBG","TTR","TH","SOX6","CALB1","SLC17A6")
pdf(paste(output_path,"Dotplot_DANeuSubMarkersOct17.pdf",sep = ""),width = 7, height = 4)
DotPlot(neurons.da, features = da.markers) +
theme(text = element_text(size=16, colour = "black"),axis.text.x = element_text(angle = 90))
Warning: Scaling data with a low number of groups may produce misleading results
dev.off()
null device
1
rg.markers <- c("CYP1B1","NEAT1","PTN","RPL41","TOP2A","VCAN","SOX2","SLIT2","HES1","VIM")
pdf(paste(output_path,"Dotplot_RGMarkersOct17.pdf",sep = ""),width = 7, height = 4)
DotPlot(rg, features = rg.markers) +
theme(text = element_text(size=16, colour = "black"),axis.text.x = element_text(angle = 90))
dev.off()
null device
1
# Apoe, Gfap, Aqp4 and Slc1a3
astro.markers <- c("COL3A1","FABP5","HPD","APOE","S100B","IGFBP2","DBI",
"PRSS56", "IGTP","LFIT3","LIGP1",
"COL1A2")
pdf(paste(output_path,"Dotplot_AstroMarkersOct17.pdf",sep = ""),width = 7, height = 4)
DotPlot(astro, features = astro.markers) +
theme(text = element_text(size=16, colour = "black"),axis.text.x = element_text(angle = 90))
Warning in FetchData.Seurat(object = object, vars = features, cells = cells) :
The following requested variables were not found: IGTP, LFIT3, LIGP1
Warning: Scaling data with a low number of groups may produce misleading results
dev.off()
null device
1
Make a label level of main cell types from the merge data
unique(seu.sc$Cell_Subtype_Markers)
[1] Neurons-GRIA2 NPC Neurons-SPARCL1 DANeurons-TPBG Neurons-CP
[6] DANeurons-RAB3B DANeurons-TTR RadialGlia-CY1B1 RadialGlia-RPL41 RadialGlia-PTN
[11] Astrocytes-FABP5 Astrocytes-HPD RadialGlia-TOP2A Mix Neurons-TPH1
[16] Neurons-TFPI1 Neurons-ASCL1 RadialGlia-NEAT1 RadialGlia-VCAN Neurons-MGP
[21] Astrocytes-COL3A1
21 Levels: Astrocytes-HPD Neurons-ASCL1 RadialGlia-RPL41 Neurons-SPARCL1 ... RadialGlia-VCAN
Idents(seu.sc) <- 'Cell_Subtype_Markers'
cluster.ids <- c("Astrocytes","Neurons","RadialGlia","Neurons",
"Astrocytes","Neurons","RadialGlia","Neurons",
"Astrocytes","Neurons","RadialGlia",
"DANeurons","Neurons","Mix","NPC",
"Neurons","DANeurons","DANeurons",
"RadialGlia","RadialGlia","RadialGlia"
)
names(cluster.ids) <- levels(seu.sc)
seu.sc <- RenameIdents(seu.sc, cluster.ids)
seu.sc$Cell_Type2 <- Idents(seu.sc)
Idents(seu.sc) <- 'Cell_Type2'
DimPlot(seu.sc)

DimPlot(seu.sc, group.by = 'Cell_Subtype_Markers')

DimPlot(seu.sc, group.by = 'Cell_Subtypes')

DimPlot(seu.sc, group.by = 'Cell_Type2')

NA
NA
# original clusters proportion of cell types in
library(reshape2)
pr.celltypes <- as.data.frame(table(seu.sc$orig.ident,seu.sc$Cell_Type2))
pr.celltypes <- reshape(pr.celltypes, idvar = "Var2", timevar = "Var1", direction = "wide")
pr.celltypes
table(seu.sc$Cell_Type2)
Astrocytes Neurons RadialGlia DANeurons Mix NPC
3082 2870 1913 476 228 154
write.csv(pr.celltypes, paste(output_path,"FreqCellTypes2inFACS.csv"))
Proportion of cell types in original FACS populations
pr
1 22 43 64
Var2 "Neurons2" "Neurons1" "Astrocytes" "RadialGlia"
Freq.DANeurons-RAB3B "131" " 76" " 0" " 52"
Freq.DANeurons-TPBG "10" "50" " 7" "46"
Freq.DANeurons-TTR "65" "20" " 0" "19"
Proportion of cell types tests
library("scProportionTest")
prop_test <- sc_utils(seu.sc)
prop_test <- permutation_test(
prop_test, cluster_identity = "Cell_Type2",
sample_1 = "Neurons1", sample_2 = "Neurons2",
sample_identity = "orig.ident"
)
permutation_plot(prop_test)

prop_test <- permutation_test(
prop_test, cluster_identity = "Cell_Type2",
sample_1 = "Neurons1", sample_2 = "RadialGlia",
sample_identity = "orig.ident"
)
permutation_plot(prop_test)

prop_test <- permutation_test(
prop_test, cluster_identity = "Cell_Type2",
sample_1 = "Neurons2", sample_2 = "RadialGlia",
sample_identity = "orig.ident"
)
*** recursive gc invocation
*** recursive gc invocation
*** recursive gc invocation
*** recursive gc invocation
*** recursive gc invocation
*** recursive gc invocation
*** recursive gc invocation
*** recursive gc invocation
*** recursive gc invocation
permutation_plot(prop_test)

prop_test <- permutation_test(
prop_test, cluster_identity = "Cell_Type2",
sample_1 = "Astrocytes", sample_2 = "RadialGlia",
sample_identity = "orig.ident"
)
permutation_plot(prop_test)

Check the proportions of subtypes of DA neurons
#library("scProportionTest")
prop_test <- sc_utils(neurons.da)
prop_test <- permutation_test(
prop_test, cluster_identity = "Cell_Subtype_Markers",
sample_1 = "Neurons1", sample_2 = "Neurons2",
sample_identity = "orig.ident"
)
permutation_plot(prop_test)

Differential gene expression between Neurons1 and Neurons2 for Other neurons and DA neurons.
down <- rownames(deg.neurons %>% filter(avg_log2FC < -6))
length(down)
[1] 8
In DA neurons
DotPlot(sub.neur, group.by = 'orig.ident', features = up.down) + RotatedAxis()
Warning: Scaling data with a low number of groups may produce misleading results

Look at the GO and other pathway analysis for the DGE
For DA neurons
pdf(paste(output_path,"GOresultesNeurons1vs2.pdf"), width = 12, height = 6)
plotEnrich(t.GObio.da1, showTerms = 10, numChar = 40, y = "Count", orderBy = "Combined.Score") +
theme(text = element_text(size=16, colour = "black"))
plotEnrich(t.GObio.da1, showTerms = 10, numChar = 40, y = "Count", orderBy = "Overlap")+
theme(text = element_text(size=16, colour = "black"))
plotEnrich(t.GObio.da2, showTerms = 10, numChar = 40, y = "Count", orderBy = "Combined.Score")+
theme(text = element_text(size=16, colour = "black"))
plotEnrich(t.GObio.da2, showTerms = 10, numChar = 40, y = "Count", orderBy = "Overlap")+
theme(text = element_text(size=16, colour = "black"))
dev.off()
null device
1
Dot plots of some up regulated genes
DotPlot(all.neurons, group.by = 'orig.ident', features = regulate.genes) + RotatedAxis()
Warning: Scaling data with a low number of groups may produce misleading results
pdf(paste(output_path,"DotPlotDEG_N1vsN2.pdf"))
DotPlot(all.neurons, group.by = 'orig.ident', features = regulate.genes) + RotatedAxis()
Warning: Scaling data with a low number of groups may produce misleading results
dev.off()
quartz_off_screen
2

BiocManager::install("clusterProfiler")
'getOption("repos")' replaces Bioconductor standard repositories, see '?repositories' for details
replacement repositories:
CRAN: https://cran.rstudio.com/
Bioconductor version 3.15 (BiocManager 1.30.18), R 4.2.1 (2022-06-23)
Installing package(s) 'clusterProfiler'
also installing the dependencies ‘blob’, ‘plogr’, ‘Biostrings’, ‘fastmatch’, ‘ggfun’, ‘ggplotify’, ‘tidytree’, ‘treeio’, ‘DBI’, ‘RSQLite’, ‘KEGGREST’, ‘DO.db’, ‘fgsea’, ‘aplot’, ‘scatterpie’, ‘shadowtext’, ‘ggtree’, ‘AnnotationDbi’, ‘downloader’, ‘DOSE’, ‘enrichplot’, ‘GO.db’, ‘GOSemSim’, ‘qvalue’, ‘yulab.utils’
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/blob_1.2.3.tgz'
Content type 'application/x-gzip' length 46035 bytes (44 KB)
==================================================
downloaded 44 KB
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/plogr_0.2.0.tgz'
Content type 'application/x-gzip' length 13193 bytes (12 KB)
==================================================
downloaded 12 KB
trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/Biostrings_2.64.1.tgz'
Content type 'application/x-gzip' length 14356457 bytes (13.7 MB)
==================================================
downloaded 13.7 MB
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/fastmatch_1.1-3.tgz'
Content type 'application/x-gzip' length 49267 bytes (48 KB)
==================================================
downloaded 48 KB
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/ggfun_0.0.7.tgz'
Content type 'application/x-gzip' length 193540 bytes (189 KB)
==================================================
downloaded 189 KB
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/ggplotify_0.1.0.tgz'
Content type 'application/x-gzip' length 137271 bytes (134 KB)
==================================================
downloaded 134 KB
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/tidytree_0.4.1.tgz'
Content type 'application/x-gzip' length 249644 bytes (243 KB)
==================================================
downloaded 243 KB
trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/treeio_1.20.2.tgz'
Content type 'application/x-gzip' length 916609 bytes (895 KB)
==================================================
downloaded 895 KB
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/DBI_1.1.3.tgz'
Content type 'application/x-gzip' length 745805 bytes (728 KB)
==================================================
downloaded 728 KB
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/RSQLite_2.2.18.tgz'
Content type 'application/x-gzip' length 4509316 bytes (4.3 MB)
==================================================
downloaded 4.3 MB
trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/KEGGREST_1.36.3.tgz'
Content type 'application/x-gzip' length 185051 bytes (180 KB)
==================================================
downloaded 180 KB
trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/fgsea_1.22.0.tgz'
Content type 'application/x-gzip' length 1489172 bytes (1.4 MB)
==================================================
downloaded 1.4 MB
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/aplot_0.1.8.tgz'
Content type 'application/x-gzip' length 56478 bytes (55 KB)
==================================================
downloaded 55 KB
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/scatterpie_0.1.8.tgz'
Content type 'application/x-gzip' length 404495 bytes (395 KB)
==================================================
downloaded 395 KB
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/shadowtext_0.1.2.tgz'
Content type 'application/x-gzip' length 226478 bytes (221 KB)
==================================================
downloaded 221 KB
trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/ggtree_3.4.4.tgz'
Content type 'application/x-gzip' length 916106 bytes (894 KB)
==================================================
downloaded 894 KB
trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/AnnotationDbi_1.58.0.tgz'
Content type 'application/x-gzip' length 5175190 bytes (4.9 MB)
==================================================
downloaded 4.9 MB
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/downloader_0.4.tgz'
Content type 'application/x-gzip' length 21727 bytes (21 KB)
==================================================
downloaded 21 KB
trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/DOSE_3.22.1.tgz'
Content type 'application/x-gzip' length 6704314 bytes (6.4 MB)
==================================================
downloaded 6.4 MB
trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/enrichplot_1.16.2.tgz'
Content type 'application/x-gzip' length 283459 bytes (276 KB)
==================================================
downloaded 276 KB
trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/GOSemSim_2.22.0.tgz'
Content type 'application/x-gzip' length 920638 bytes (899 KB)
==================================================
downloaded 899 KB
trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/qvalue_2.28.0.tgz'
Content type 'application/x-gzip' length 2801783 bytes (2.7 MB)
==================================================
downloaded 2.7 MB
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.2/yulab.utils_0.0.5.tgz'
Content type 'application/x-gzip' length 33694 bytes (32 KB)
==================================================
downloaded 32 KB
trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/clusterProfiler_4.4.4.tgz'
Content type 'application/x-gzip' length 821345 bytes (802 KB)
==================================================
downloaded 802 KB
The downloaded binary packages are in
/var/folders/k4/khtkczkd5tn732ftjpwgtr240000gn/T//RtmpOFXQrS/downloaded_packages
installing the source packages ‘DO.db’, ‘GO.db’
trying URL 'https://bioconductor.org/packages/3.15/data/annotation/src/contrib/DO.db_2.9.tar.gz'
Content type 'application/x-gzip' length 1769978 bytes (1.7 MB)
==================================================
downloaded 1.7 MB
trying URL 'https://bioconductor.org/packages/3.15/data/annotation/src/contrib/GO.db_3.15.0.tar.gz'
Content type 'application/x-gzip' length 29908485 bytes (28.5 MB)
==================================================
downloaded 28.5 MB
* installing *source* package ‘DO.db’ ...
** using staged installation
** R
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (DO.db)
* installing *source* package ‘GO.db’ ...
** using staged installation
** R
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (GO.db)
The downloaded source packages are in
‘/private/var/folders/k4/khtkczkd5tn732ftjpwgtr240000gn/T/RtmpOFXQrS/downloaded_packages’
Old packages: 'BiocParallel', 'brew', 'cli', 'clue', 'commonmark', 'cpp11', 'crayon', 'curl',
'data.table', 'DelayedMatrixStats', 'devtools', 'digest', 'dotCall64', 'evaluate', 'foreign',
'gert', 'ggforce', 'ggraph', 'ggridges', 'graphlayouts', 'igraph', 'irlba', 'isoband',
'jsonlite', 'lifecycle', 'limma', 'mnormt', 'nlme', 'nnet', 'openssl', 'pracma', 'purrr',
'ragg', 'rainbow', 'RcppArmadillo', 'RCurl', 'readr', 'rlang', 'rmarkdown', 'sctransform',
'Seurat', 'SeuratObject', 'SingleCellExperiment', 'sys', 'testthat', 'tidyselect', 'tinytex',
'vctrs', 'vroom', 'XML', 'yaml'
Update all/some/none? [a/s/n]:
n
BiocManager::install("pathview")
'getOption("repos")' replaces Bioconductor standard repositories, see '?repositories' for details
replacement repositories:
CRAN: https://cran.rstudio.com/
Bioconductor version 3.15 (BiocManager 1.30.18), R 4.2.1 (2022-06-23)
Installing package(s) 'pathview'
also installing the dependencies ‘KEGGgraph’, ‘org.Hs.eg.db’
trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/KEGGgraph_1.56.0.tgz'
Content type 'application/x-gzip' length 1665739 bytes (1.6 MB)
==================================================
downloaded 1.6 MB
trying URL 'https://bioconductor.org/packages/3.15/bioc/bin/macosx/contrib/4.2/pathview_1.36.1.tgz'
Content type 'application/x-gzip' length 2700402 bytes (2.6 MB)
==================================================
downloaded 2.6 MB
The downloaded binary packages are in
/var/folders/k4/khtkczkd5tn732ftjpwgtr240000gn/T//RtmpOFXQrS/downloaded_packages
installing the source package ‘org.Hs.eg.db’
trying URL 'https://bioconductor.org/packages/3.15/data/annotation/src/contrib/org.Hs.eg.db_3.15.0.tar.gz'
Content type 'application/x-gzip' length 83788492 bytes (79.9 MB)
==================================================
downloaded 79.9 MB
* installing *source* package ‘org.Hs.eg.db’ ...
** using staged installation
** R
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (org.Hs.eg.db)
The downloaded source packages are in
‘/private/var/folders/k4/khtkczkd5tn732ftjpwgtr240000gn/T/RtmpOFXQrS/downloaded_packages’
Old packages: 'BiocParallel', 'brew', 'cli', 'clue', 'commonmark', 'cpp11', 'crayon', 'curl',
'data.table', 'DelayedMatrixStats', 'devtools', 'digest', 'dotCall64', 'evaluate', 'foreign',
'gert', 'ggforce', 'ggraph', 'ggridges', 'graphlayouts', 'igraph', 'irlba', 'isoband',
'jsonlite', 'lifecycle', 'limma', 'mnormt', 'nlme', 'nnet', 'openssl', 'pracma', 'purrr',
'ragg', 'rainbow', 'RcppArmadillo', 'RCurl', 'readr', 'rlang', 'rmarkdown', 'sctransform',
'Seurat', 'SeuratObject', 'SingleCellExperiment', 'sys', 'testthat', 'tidyselect', 'tinytex',
'vctrs', 'vroom', 'XML', 'yaml'
Update all/some/none? [a/s/n]:
n
BiocManager::install("enrichplot")
'getOption("repos")' replaces Bioconductor standard repositories, see '?repositories' for details
replacement repositories:
CRAN: https://cran.rstudio.com/
Bioconductor version 3.15 (BiocManager 1.30.18), R 4.2.1 (2022-06-23)
Warning: package(s) not installed when version(s) same as current; use `force = TRUE` to re-install:
'enrichplot'
Old packages: 'BiocParallel', 'brew', 'cli', 'clue', 'commonmark', 'cpp11', 'crayon', 'curl',
'data.table', 'DelayedMatrixStats', 'devtools', 'digest', 'dotCall64', 'evaluate', 'foreign',
'gert', 'ggforce', 'ggraph', 'ggridges', 'graphlayouts', 'igraph', 'irlba', 'isoband',
'jsonlite', 'lifecycle', 'limma', 'mnormt', 'nlme', 'nnet', 'openssl', 'pracma', 'purrr',
'ragg', 'rainbow', 'RcppArmadillo', 'RCurl', 'readr', 'rlang', 'rmarkdown', 'sctransform',
'Seurat', 'SeuratObject', 'SingleCellExperiment', 'sys', 'testthat', 'tidyselect', 'tinytex',
'vctrs', 'vroom', 'XML', 'yaml'
Update all/some/none? [a/s/n]:
n
library(clusterProfiler)
clusterProfiler v4.4.4 For help: https://yulab-smu.top/biomedical-knowledge-mining-book/
If you use clusterProfiler in published research, please cite:
T Wu, E Hu, S Xu, M Chen, P Guo, Z Dai, T Feng, L Zhou, W Tang, L Zhan, X Fu, S Liu, X Bo, and G Yu. clusterProfiler 4.0: A universal enrichment tool for interpreting omics data. The Innovation. 2021, 2(3):100141
Attaching package: ‘clusterProfiler’
The following object is masked from ‘package:reshape’:
rename
The following object is masked from ‘package:stats’:
filter
library(enrichplot)
# we use ggplot2 to add x axis labels (ex: ridgeplot)
library(ggplot2)
Try with cluster profiler
emapplot(gse, showCategory = 10)
Error in has_pairsim(x) :
Term similarity matrix not available. Please use pairwise_termsim function to deal with the results of enrichment analysis.
Predict cell types again to make table 12 Organoids in house data
seu.r <- AIW120
colnames(seu.r@meta.data)
[1] "orig.ident" "nCount_RNA"
[3] "nFeature_RNA" "percent.mt"
[5] "predicted.id" "prediction.score.RGa"
[7] "prediction.score.Astrocytes.2" "prediction.score.Neurons.e"
[9] "prediction.score.Oligodendrocytes" "prediction.score.Neurons.DA"
[11] "prediction.score.Neural.Precursors" "prediction.score.Neurons.i"
[13] "prediction.score.Neurons" "prediction.score.Other"
[15] "prediction.score.Epithelial" "prediction.score.Astrocytes.1"
[17] "prediction.score.RGd1" "prediction.score.RGd2"
[19] "prediction.score.max" "pred.165days"
[21] "RNA_snn_res.0" "RNA_snn_res.0.05"
[23] "RNA_snn_res.0.25" "RNA_snn_res.0.5"
[25] "RNA_snn_res.0.8" "seurat_clusters"
[27] "RNA_snn_res.0.9" "RNA_snn_res.1"
[29] "RNA_snn_res.1.2" "res08names"
[31] "res08names2" "res08names.gene2"
[33] "main.genotype" "res08names.gene3"
[35] "res08names3"
anchors <- FindTransferAnchors(reference = seu.r, query = seu.q, dims = 1:25)
Performing PCA on the provided reference using 2000 features as input.
Projecting cell embeddings
Finding neighborhoods
Finding anchors
Found 4595 anchors
Filtering anchors
Retained 2761 anchors
as(<ngCMatrix>, "dgCMatrix") is deprecated since Matrix 1.5-0; do as(., "dMatrix") instead
print("getting predictions")
[1] "getting predictions"
predictions <- TransferData(anchorset = anchors, refdata = seu.r$res08names2, k.weight = 50)
Finding integration vectors
Finding integration vector weights
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Predicting cell labels
seu.q <- AddMetaData(seu.q, predictions$predicted.id, col.name = "prediction")
seu.q <- AddMetaData(seu.q, predictions$prediction.score.max, col.name = "prediction.score.max")
seu.q$AIW120.pred <- ifelse(seu.q$prediction.score.max > 0.8, seu.q$prediction, "none")
DimPlot(seu.q, group.by = 'AIW120.pred')

More predictions Developing brain: Cortex Forebrain
Adult brain: whole brain with subtypes Adult brain midbrain and striatum Adult brain midbrain main cell types Adult brain DA or Astro subtypes

Tables of top predictions
t.lables <- as.data.frame(table(seu.q$Cell_Subtype_Markers,seu.q$devcortex))
t.lables$Freq <- as.double(t.lables$Freq)
top.prediction <-as.data.frame(t.lables %>% group_by(Var1) %>% top_n(1, Freq))
top.prediction
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKUmVhZCBpbiB0aGUgbGFiZWxsZWQgb2JqZWN0IApSdW4gdGhlIGNvcnJlbGF0aW9uIGNvbXBhcmlzb24gYmV0d2VlbiB0aGUgdG90YWwgc2NSTkEgcGVyIEZBQ1MgcG9wIGFuZCB0aGUgQUIgbGV2ZWxzCkNhbGN1bGF0ZSB0aGUgcHJvcG9ydGlvbiBvZiB0aGUgY2VsbCB0eXBlcyBmcm9tIHRoZSBvcmdpbmFsIGxhYmVscwpVTUFQIG9mIHRoZSBjZWxsIFBPUFMgbWVyZ2VkClVNQVAgb2YgdGhlIHN1YnR5cGVzIGxhYmVsbGVkCgoKCgpgYGB7cn0KCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KCdyZXNoYXBlJykKbGlicmFyeSgiZ2dwbG90MiIpCgoKYGBgCgoKUmVhZCBpbiB0aGUgbGFibGVsZWQgb2JqZWN0IHNpbmdsZSBjZWxsIHNlcXVlbmNpbmcKCmBgYHtyfQoKcGF0aHdheSA8LSAiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL0RhdGEvc2NSTkFzZXEvUGhlbm9JRC9zY1JOQXNlcVNvcnRlZC9vYmpzLyIKc2V1LnNjIDwtIHJlYWRSRFMocGFzdGUocGF0aHdheSwgIkNvbWJpbmVkTGFiZWxlZE1hcmtlcnMxNDEwMjAyMi5SRFMiKSkKc2F2ZVJEUyhzZXUuc2MscGFzdGUocGF0aHdheSwgIkNvbWJpbmVkTGFiZWxlZE1hcmtlcnMxNDEwMjAyMi5SRFMiKSkKCmBgYAoKClJlYWQgaW4gdGhlIEZsb3cgQ3l0b21ldHJ5IGRhdGEKCmBgYHtyfQpvdXRwdXRfcGF0aCA9ICIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb2N1bWVudHMvRGF0YS9GbG93Q3l0b21ldHJ5L1BoZW5vSUQvQW5hbHlzaXMvUGFwZXJGaWd1cmVzL1Bvc3RTb3J0R2F0aW5nUG9wcy8iCnNldS5mYyA8LSByZWFkUkRTKHBhc3RlKG91dHB1dF9wYXRoLCJqdW5lMTBwb3N0U29ydC5zZXUuUkRTIiwgc2VwID0gIiIpKQp1bmlxdWUoc2V1LmZjJEdhdGVkUG9wKQoKIyBib3RoIG5ldXJvbnMxIGFuZCBuZXVyb25zMiBhcmUgbWl4ZWQgaWUgd2hhdCBJIGxhYmVsbGVkIGJlZm9yZSBzb3J0aW5nIGFzIG5ldXJvbnMxIChDRDI0KysrKSB3YXMgbGFiZWxsZWQgYXMgTmV1cm9uczIgaW4gdGhlIGV4cGVpbWVudAoKYGBgCgpNYXJrZXIgbGlzdAoKYGBge3J9CgptYXJrZXIuYWIgPC0gYygiQ0QyNCIsIkNENTYiLCJDRDI5IiwiQ0QxNSIsIkNEMTg0IiwiQ0QxMzMiLCJDRDcxIiwiQ0Q0NCIsIkdMQVNUIiwiQVFQNCIsIkhlcGFDQU0iLCAiQ0QxNDBhIiwiTzQiKQoKbWFya2VyLmdlbmVzIDwtYygiQ0QyNCIsIk5DQU0xIiwiSVRHQjEiLCJGVVQ0IiwiQ1hDUjQiLCJQUk9NMSIsIlRGUkMiLCJDRDQ0IiwiU0xDMUEzIiwiQVFQNCIsIkhFUEFDQU0iLCAiUERHRlJBIiwiTktYNi0yIikKCmBgYAoKCk1ha2UgdGhlIGV4cHJlc3Npb24gbWF0cml4ZXMKCmBgYHtyfQpJZGVudHMoc2V1LnNjKSA8LSAnb3JpZy5pZGVudCcKRGVmYXVsdEFzc2F5KHNldS5zYykgPC0gJ1JOQScKCiMgdG8gaW5jbHVkZSBhbGwgZ2VuZXMgaW4gc2NhbGUgZGF0YSBhZGQgdGhlIGZlYXR1cmVzIGFyZ3VtZW50CnNldS5zYyA8LSBTY2FsZURhdGEob2JqZWN0ID0gc2V1LnNjLCBmZWF0dXJlcyA9IHJvd25hbWVzKHNldS5zYykpCgoKc2NSTkFzZXEubWVhbiA8LSBhcy5kYXRhLmZyYW1lKEF2ZXJhZ2VFeHByZXNzaW9uKHNldS5zYyxmZWF0dXJlcyA9IG1hcmtlci5nZW5lcywgYXNzYXlzID0gJ1JOQScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAuYnkgPSAnb3JpZy5pZGVudCcsIHNsb3Q9ICdzY2FsZS5kYXRhJykpCgoKIyBjaGFuZ2UgZ2VuZSBuYW1lcyB0byBwcm90ZWluL0FCIG5hbWVzCnJvd25hbWVzKHNjUk5Bc2VxLm1lYW4pIDwtIG1hcmtlci5hYgoKIyBnZXQgdGhlIG1lYW4gZXhwcmVzc2lvbiBmcm9tIEZBQ1MgCkRlZmF1bHRBc3NheShzZXUuZmMpIDwtICdSTkEnCklkZW50cyhzZXUuZmMpIDwtICdHYXRlZFBvcCcKCiNzZXUuZmMgPC0gU2NhbGVEYXRhKHNldS5mYykKCkZDLm1lYW4gPC0gYXMuZGF0YS5mcmFtZShBdmVyYWdlRXhwcmVzc2lvbihzZXUuZmMsIGFzc2F5cyA9ICdSTkEnLGZlYXR1cmVzID0gbWFya2VyLmFiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gJ0dhdGVkUG9wJywgc2xvdD0gJ3NjYWxlLmRhdGEnKSkKCgpgYGAKCkNhbGN1bGF0ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHR3byBtYXRyaXhlcwoKYGBge3J9CgojIHJlbmFtZSBhbmQgcmVvcmRlciBkYXRhZnJhbWVzIHRvIG1hdGNoCmNvbG5hbWVzKEZDLm1lYW4pCmNvbG5hbWVzKEZDLm1lYW4pIDwtIGMoIkFzdHJvY3l0ZXMiLCJSYWRpYWxHbGlhIiwiTmV1cm9uczIiLCJOZXVyb25zMSIpCmNvbG5hbWVzKEZDLm1lYW4pCgpjb2xuYW1lcyhzY1JOQXNlcS5tZWFuKQpjb2xuYW1lcyhzY1JOQXNlcS5tZWFuKSA8LSBjKCJOZXVyb25zMiIsIk5ldXJvbnMxIiwiQXN0cm9jeXRlcyIsIlJhZGlhbEdsaWEiKQpjb2xuYW1lcyhzY1JOQXNlcS5tZWFuKQpybmEubWVhbiA8LSBzY1JOQXNlcS5tZWFuICU+JSBzZWxlY3QoIkFzdHJvY3l0ZXMiLCJSYWRpYWxHbGlhIiwiTmV1cm9uczEiLCJOZXVyb25zMiIpCkZDLm1lYW4gPC0gRkMubWVhbiAlPiUgc2VsZWN0KCJBc3Ryb2N5dGVzIiwiUmFkaWFsR2xpYSIsIk5ldXJvbnMxIiwiTmV1cm9uczIiKQoKZGYuY29yIDwtIGNvcihGQy5tZWFuLCBybmEubWVhbikKIyBmaXJzdCBvbmUgaXMgdGhlIHJvd3MgYW5kIHNlY29uZCBpcyB0aGUgY29sdW1ucywgRkMgbWVhc3VyZXMgb24gdGhlIHkgYXhpcwoKZGYuY29yCgoKIyBOZXVyb25zMiBzaG91bGQgYmUgdGhlIGhpZ2ggQ0Q1NiBwb3B1bGF0aW9uIGFuZCBpdCBpcyBpbiBib3RoIGNhc2VzIAojIE5ldXJvbnMxIHNob3VsZCBiZSB0aGUgaGlnaCBDRDI0IGFuZCBpdCBpcwoKRkMubWVhbgpybmEubWVhbgoKIyB0cnkgY2FsY3VsYXRpbmcgeiBzY29yZXMKIyB0aGlzIHdvcmtzIG9uIHJvd3MKZGF0YSA8LSBGQy5tZWFuCmFkZC5yb3duYW1lcyA8LSByb3duYW1lcyhkYXRhKQpGQy5tZWFuLnogPC0gYXMuZGF0YS5mcmFtZShzYXBwbHkoZGF0YSwgZnVuY3Rpb24oZGF0YSkgKGRhdGEtbWVhbihkYXRhKSkvc2QoZGF0YSkpKQoKcm93bmFtZXMoRkMubWVhbi56KSA8LWFkZC5yb3duYW1lcwpGQy5tZWFuLnoKCgpkYXRhIDwtIHJuYS5tZWFuCmFkZC5yb3duYW1lcyA8LSByb3duYW1lcyhkYXRhKQpybmEubWVhbi56IDwtIGFzLmRhdGEuZnJhbWUoc2FwcGx5KGRhdGEsIGZ1bmN0aW9uKGRhdGEpIChkYXRhLW1lYW4oZGF0YSkpL3NkKGRhdGEpKSkKCnJvd25hbWVzKHJuYS5tZWFuLnopIDwtYWRkLnJvd25hbWVzCnJuYS5tZWFuLnoKCgpkZi5jb3IgPC0gY29yKEZDLm1lYW4ueiwgcm5hLm1lYW4ueikKZGYuY29yCgp3cml0ZS5jc3YoZGYuY29yLCBwYXN0ZShvdXRwdXRfcGF0aCwiQ29ycmVsYXRpb25zRkNzY1JOQXNlcS5jc3YiKSkKCgpgYGAKClBsb3QgdGhlIGhlYXRtYXAKRmlndXJlIDZBCgpgYGB7cn0KIyBuZWVkIHRvIG1lbHQgdGhlIG1hdHJpeApsb25nRGF0YTwtIG1lbHQoZGYuY29yKQoKaGVhZChsb25nRGF0YSkKY29sbmFtZXMobG9uZ0RhdGEpIDwtIGMoIkZDIiwic2NSTkEiLCJSMiIpCgpnZ3Bsb3QobG9uZ0RhdGEsIGFlcyh4PXNjUk5BLHk9RkMsIGZpbGwgPVIyKSkgKyBnZW9tX3RpbGUoKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudDIobG93ID0gIiMwNzVBRkYiLAogICAgICAgICAgICAgICAgICAgICAgIG1pZCA9ICIjRkZGRkNDIiwKICAgICAgICAgICAgICAgICAgICAgICBoaWdoID0gIiNGRjAwMDAiKSArCiAgIGd1aWRlcyhmaWxsID0gZ3VpZGVfY29sb3VyYmFyKGxhYmVsID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWNrcyA9IEZBTFNFKSkgKyB0aGVtZV9idygpICsKICBjb29yZF9maXhlZCgpICArc2NhbGVfeF9kaXNjcmV0ZShleHBhbmQ9YygwLDApKSsKICBzY2FsZV95X2Rpc2NyZXRlKGV4cGFuZD1jKDAsMCkpKyB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGNvbG91ciA9ICJibGFjayIpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCwgY29sb3VyID0gImJsYWNrIiwgYW5nbGUgPSA5MCksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9IDE4LCBjb2xvdXIgPSAiYmxhY2siKSkgICsgeGxhYignc2NSTkFzZXEnKSArIHlsYWIoJ0Zsb3cgQ3l0b21ldHJ5JykgCgpvdXRwdXRfcGF0aCA8LSAiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL1Byb2plY3RzX1BhcGVycy9QaGVub0lEL0ZvckZpZ3VyZXMvc2NSTkEvIgoKcGRmKHBhc3RlKG91dHB1dF9wYXRoLCJGQ19zY1JOQV9jb3JyZWxhdGlvbk9jdDE2LnBkZiIpLCB3aWR0aCA9IDgsIGhlaWdodCA9IDUpCmdncGxvdChsb25nRGF0YSwgYWVzKHg9c2NSTkEseT1GQywgZmlsbCA9UjIpKSArIGdlb21fdGlsZSgpICsKICBzY2FsZV9maWxsX2dyYWRpZW50Mihsb3cgPSAiIzA3NUFGRiIsCiAgICAgICAgICAgICAgICAgICAgICAgbWlkID0gIiNGRkZGQ0MiLAogICAgICAgICAgICAgICAgICAgICAgIGhpZ2ggPSAiI0ZGMDAwMCIsIG1pZHBvaW50ID0gMCwgbGltaXQgPSBjKC0wLjUsMC41KSkgKwogICBndWlkZXMoZmlsbCA9IGd1aWRlX2NvbG91cmJhcihsYWJlbCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlja3MgPSBGQUxTRSkpICsgdGhlbWVfYncoKSArCiAgY29vcmRfZml4ZWQoKSAgK3NjYWxlX3hfZGlzY3JldGUoZXhwYW5kPWMoMCwwKSkgKwogIHNjYWxlX3lfZGlzY3JldGUoZXhwYW5kPWMoMCwwKSkgKyAKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGNvbG91ciA9ICJibGFjayIpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiwgY29sb3VyID0gImJsYWNrIiwgYW5nbGUgPSA5MCksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemU9IDE2LCBjb2xvdXIgPSAiYmxhY2siKSkgICsgeGxhYignc2NSTkFzZXEnKSArIHlsYWIoJ0Zsb3cgQ3l0b21ldHJ5JykgCgpkZXYub2ZmKCkKCgoKCmBgYAoKQ29tcGFyZSBwcm9wb3J0aW9ucyBvZiBjZWxscyBpbiBlYWNoIEZBQ1MgcG9wIC0gRmlndXJlIDZCCgpgYGB7cn0KCiMgc2F2ZSB0aGUgcHJvcG9ydGlvbiBjaGFydCB3aXRoIGNvbG91cnMgbWF0Y2hpbmcgdGhlIFVNQVBzIApkZiA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKHNldS5zYyRvcmlnLmlkZW50LCBzZXUuc2MkQ2VsbF9UeXBlcykpCgojIHRoZSBjaGFydCB3aWxsIGRlZmF1bHQgdG8gYWxwaGFiZXRpY2FsCgpjbHVzdC5jb2xvdXJzIDwtIGMoImNob2NvbGF0ZTEiLCJkZWVwc2t5Ymx1ZSIsInN0ZWVsYmx1ZTQiLCJtZWRpdW1wdXJwbGUzIiwicmVkMiIsImJ1cmx5d29vZDMiLCAgICAgInBpbmsyIikKCiMgYnV0IG5vdCBmb3IgdGhlIHggYXhpcyAtIHJlb3JkZXIgd2l0aCBmYWN0b3IgdG8gbWF0Y2ggZmlndXJlIDZBCmRmJEZBQ3BvcCA8LSBmYWN0b3IoZGYkVmFyMSwgbGV2ZWxzID0gYygiQXN0cm9jeXRlcyIsIlJhZGlhbEdsaWEiLCJOZXVyb25zMSIsIk5ldXJvbnMyIikpCgpwZGYocGFzdGUob3V0cHV0X3BhdGgsIkJhckNoYXJ0UHJvcG9ydGlvbkNlbGxUeXBlc2luNHBvcHNPY3QxNi5wZGYiKSwgaGVpZ2h0ID0gNSwgd2lkdGggPSA2KQpnZ3Bsb3QoZGYsIGFlcyh4ID0gRkFDcG9wLCB5ID0gRnJlcSwgZmlsbCA9IFZhcjIpKSArIAogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKSArIHRoZW1lX2NsYXNzaWMoKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2x1c3QuY29sb3VycykgKwogICNzY2FsZV94X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLDApKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgc2l6ZSA9IDE2KSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSkgKwogIGxhYnMoeSA9ICJQcm9wb3J0aW9uIG9mIENlbGxzIiwgeCA9ICIiKSArCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKSAKZGV2Lm9mZigpCgpgYGAKCgpNYWtlIGEgdGFibGUgb2YgY2VsbCB0eXBlcwoKYGBge3J9CgpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkocmVzaGFwZSkKCiMgZm9yIG9yaWdpbmFsIGNlbGwgdHlwZXMgCgoKZGYuciA8LSByZXNoYXBlKGRmLCBpZHZhciA9ICJWYXIyIiwgdGltZXZhciA9ICJWYXIxIiwgZGlyZWN0aW9uID0gIndpZGUiKQpkYXQxIDwtIGRmLnIKZGF0MVtdIDwtIGxhcHBseShkYXQxW10sIGZ1bmN0aW9uKHgpewogICMgQ2hlY2sgaWYgdGhlIGNvbHVtbiBpcyBudW1lcmljCiAgaWYgKGlzLm51bWVyaWMoeCkpewogICAgcmV0dXJuKHgvc3VtKHgpKjEwMCkKICB9IGVsc2V7CiAgICByZXR1cm4oeCkKICB9Cn0pCmRhdDEKd3JpdGUuY3N2KGRhdDEsIHBhc3RlKG91dHB1dF9wYXRoLCJwcm9wb3J0aW9ub2ZDZWxsdHlwZXNpbjRwb3BzLmNzdiIpKQoKCgoKYGBgCgoKClVNQVAgd2l0aCBvcmlnaW5hbCBpZGVudHMgdG8gc2hvdyBvdmVybGFwIChvciBsYWNrIHRoZXJlIG9mKQpGaWd1cmUgNkMKCmBgYHtyfQojIEZpZ3VyZSA2IEMKIyBVTUFQIHdpdGggdGhlIDQgb3JpZy5pZGVudHMKCnNhbXBsZS5vcmRlciA8LSBjKCJBc3Ryb2N5dGVzIiwiUmFkaWFsR2xpYSIsIk5ldXJvbnMxIiwiTmV1cm9uczIiKQpzYW1wbGUub3JkZXIgPC0gcmV2KHNhbXBsZS5vcmRlcikKCiMgY29sb3VyIG9yZGVyIHRvIG1hdGNoIGNlbGwgdHlwZSBvcmRlcgpjbHVzdC5jb2xvdXJzIDwtIGMoInJveWFsYmx1ZSIsICJpbmRpYW5yZWQyIiwicGFsZWdyZWVuMiIsInNwcmluZ2dyZWVuNCIpCiAKSWRlbnRzKHNldS5zYykgPC0gJ29yaWcuaWRlbnQnCgpSdW5VTUFQKCkKRGltUGxvdChzZXUuc2MsIG9yZGVyID0gc2FtcGxlLm9yZGVyLCBjb2xzID0gY2x1c3QuY29sb3Vycywgc2h1ZmZsZSA9IFRSVUUsIHJhc3Rlcj1GQUxTRSwgcHQuc2l6ZSA9IDAuMSwgbGFiZWwgPSBGQUxTRSkKCm91dHB1dF9wYXRoIDwtICIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb2N1bWVudHMvUHJvamVjdHNfUGFwZXJzL1BoZW5vSUQvRm9yRmlndXJlcy9zY1JOQS8iCgojIyMgRmlndXJlIDZDCgpwZGYocGFzdGUob3V0cHV0X3BhdGgsIlVNQVBzY1JOQXNlcU1lcmdlNE9jdDE2LnBkZiIpLHdpZHRoID0gNywgaGVpZ2h0ID0gNCkKRGltUGxvdChzZXUuc2MsIG9yZGVyID0gc2FtcGxlLm9yZGVyLCBjb2xzID0gY2x1c3QuY29sb3Vycywgc2h1ZmZsZSA9IFRSVUUsIHJhc3Rlcj1GQUxTRSwgcHQuc2l6ZSA9IDAuMSwgbGFiZWwgPSBGQUxTRSwgbGFiZWwuc2l6ZSA9IDYpICsKICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLCAKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPTE2KSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0xNikpCmRldi5vZmYoKQoKCiMjIEZpZ3VyZSBTMjMgcGFuZWwgCgpjZWxsLm9yZGVyIDwtIGMoIkFzdHJvY3l0ZXMiLCJFbmRvdGhlbGlhbCIsIkdsaWEiLCJOUEMiLCJOZXVyb25zIiwiT3RoZXIiLCJSYWRpYWwgR2xpYSIpCmNlbGwub3JkZXIgPC0gcmV2KGNlbGwub3JkZXIpCgojIGNvbG91ciBvcmRlciB0byBtYXRjaCBjZWxsIHR5cGUgb3JkZXIKY2x1c3QuY29sb3VycyA8LSBjKCJjaG9jb2xhdGUxIiwiZGVlcHNreWJsdWUiLCJzdGVlbGJsdWU0IiwicmVkMiIsIm1lZGl1bXB1cnBsZTMiLCJidXJseXdvb2QzIiwgCiAgICAgICAgICAgICAgICAgICAicGluazIiKQoKIApJZGVudHMoc2V1LnNjKSA8LSAnQ2VsbF9UeXBlcycKICAgICAgCiMgZGVzaWduYXRlZCB0aGUgb3JkZXIgb2YgdGhlIHNwbGl0cyBmYWN0b3IKc2V1LnNjJG9yaWcuaWRlbnQgPC0gZmFjdG9yKHggPSBzZXUuc2Mkb3JpZy5pZGVudCwgbGV2ZWxzID0gYygiQXN0cm9jeXRlcyIsIlJhZGlhbEdsaWEiLCJOZXVyb25zMSIsIk5ldXJvbnMyIikpCgoKRGltUGxvdChzZXUuc2MsIG9yZGVyID0gY2VsbC5vcmRlciwgY29scyA9IGNsdXN0LmNvbG91cnMsIHNodWZmbGUgPSBUUlVFLCByYXN0ZXI9RkFMU0UsIHB0LnNpemUgPSAwLjEsIGxhYmVsID0gRkFMU0UsIHNwbGl0LmJ5ID0gJ29yaWcuaWRlbnQnLCBuY29sID0gMikKCgoKCnBkZihwYXN0ZShvdXRwdXRfcGF0aCwiVU1BUF9tZXJnZV9zcGxpdGJ5b3JpZ2lkZW50T2N0MTYucGRmIiksd2lkdGggPSAxMiwgaGVpZ2h0ID0gNy41KQpEaW1QbG90KHNldS5zYywgb3JkZXIgPSBjZWxsLm9yZGVyLCBjb2xzID0gY2x1c3QuY29sb3Vycywgc2h1ZmZsZSA9IFRSVUUsIHJhc3Rlcj1GQUxTRSwgcHQuc2l6ZSA9IDAuMSwgbGFiZWwgPSBGQUxTRSwgc3BsaXQuYnkgPSAnb3JpZy5pZGVudCcsIGxhYmVsLnNpemUgPSA2LCBuY29sID0gMikgKwogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksIAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9MTYpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPTE2KSkKZGV2Lm9mZigpCgoKIyBhbHNvIHBsb3Qgb25lIG5vdCBzcGxpdCB0byBzZWUgdGhlIHdob2xlIHRoaW5nCgoKcGRmKHBhc3RlKG91dHB1dF9wYXRoLCJVTUFQX21lcmdlX0NlbGxUeXBlc09jdDE2LnBkZiIpLHdpZHRoID0gNi43LCBoZWlnaHQgPSA0LjEpCkRpbVBsb3Qoc2V1LnNjLCBvcmRlciA9IGNlbGwub3JkZXIsIGNvbHMgPSBjbHVzdC5jb2xvdXJzLCBzaHVmZmxlID0gVFJVRSwgcmFzdGVyPUZBTFNFLCBwdC5zaXplID0gMC4xLCBsYWJlbCA9IEZBTFNFLCBsYWJlbC5zaXplID0gNikgKwogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTYpLCBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksIAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9MTYpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPTE2KSkKZGV2Lm9mZigpCgoKCgoKYGBgCgpGaWd1cmUgNkQgLSBVTUFQIHdpdGggc3ViZ3JvdXBzCgpgYGB7cn0KCnVuaXF1ZShzZXUuc2MkQ2VsbF9TdWJ0eXBlX01hcmtlcnMpCiMgMjEgbGV2ZWxzIHdpbGwgbmVlZCAyMSBjb2xvdXJzIAojIE5ldXJvbnMgLSBwdXJwbGVzCiMgREEgbmV1cm9ucyBncmVlbgojIE5QQyByZWQKIyBBc3Ryb2N5dGVzIC0gT3JhbmdlIC0KIyBSYWRpYWwgR2xpYSAtIFBpbmsgeWVsbG93CiMgb3RoZXIgY2VsbHMgYmx1ZXMKCnNhbXBsZS5vcmRlciA8LSBjKCJBc3Ryb2N5dGVzLUNPTDNBMSIsIkFzdHJvY3l0ZXMtRkFCUDUiLCAiQXN0cm9jeXRlcy1IUEQiLAogICAgICAgICAgICAgICAgICAiREFOZXVyb25zLVJBQjNCIiwiREFOZXVyb25zLVRQQkciLCJEQU5ldXJvbnMtVFRSIiwKICAgICAgICAgICAgICAgICAgIk1peCIsIk5QQyIsCiAgICAgICAgICAgICAgICAgICJOZXVyb25zLUFTQ0wxIiwKICAgICAgICAgICAgICAgICAgIk5ldXJvbnMtQ1AiLCJOZXVyb25zLUdSSUEyIiwKICAgICAgICAgICAgICAgICAgIk5ldXJvbnMtTUdQIiwKICAgICAgICAgICAgICAgICAgIk5ldXJvbnMtU1BBUkNMMSIsCiAgICAgICAgICAgICAgICAgICJOZXVyb25zLVRQSDEiLCAiTmV1cm9ucy1URlBJMSIsCiAgICAgICAgICAgICAgICAgICJSYWRpYWxHbGlhLUNZMUIxIiwgIlJhZGlhbEdsaWEtTkVBVDEiLCJSYWRpYWxHbGlhLVBUTiIsCiAgICAgICAgICAgICAgICAgICJSYWRpYWxHbGlhLVJQTDQxIiwgIlJhZGlhbEdsaWEtVE9QMkEiLCAiUmFkaWFsR2xpYS1WQ0FOIikKc2FtcGxlLm9yZGVyIDwtIHJldihzYW1wbGUub3JkZXIpCgoKY2x1c3QuY29sb3VycyA8LSBjKCIjRjFDMTY2IiwiI0ZGOTQwMCIsIiNFOTU5MDEiLCAgICAgICAgICAjIG9yYW5nZXMgQXN0cm9jeXRlcwogICAgICAgICAgICAgICAgICAgIiM0M0Q1OUMiLCIjN0RBNjk2IiwiIzE1QUUzNiIsICAgICAjIGdyZWVucyBEQSBuZXVyb25zCiAgICAgICAgICAgICAgICAgICAic3RlZWxibHVlIiwicmVkMiIsICAgIyBtaXggYW5kIE5QQwogICAgICAgICAgICAgICAgICAgIiM4RjY3RkYiLAogICAgICAgICAgICAgICAgICAgIiM2ODQwREIiLCIjOUI4QkM3IiwgICAjIG5ldXJvbnMgMiAgQ1AsIEdSSUEyCiAgICAgICAgICAgICAgICAgICAiIzdCMjJGQiIsICAgICMgTUdQCiAgICAgICAgICAgICAgICAgICAicHVycGxlIiwgIyBTUEFSQ0wxCiAgICAgICAgICAgICAgICAgICAiIzk4NjNFNSIsIiM4RTM2RDIiLCAjIFRQSDEsIFRGUEkxCiAgICAgICAgICAgICAgICAgICAiI0Y2OEQ4RCIsICMgUkcgQ1kxQjEKICAgICAgICAgICAgICAgICAgICIjRjY4ODg4IiwiI0Y2ODhCRCIsICAgIyBSRyBORUFUMSwgUFROIAogICAgICAgICAgICAgICAgICAgIiNGNTI4OEEiLCIjREM1N0NGIiwiI0YzQTZFQyIpCgojRGltUGxvdChzZXUuc2MsIHB0LnNpemUgPSAwLjEsIG9yZGVyID0gc2FtcGxlLm9yZGVyLCBsYWJlbCA9IFRSVUUsIGdyb3VwLmJ5ID0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJykKSWRlbnRzKHNldS5zYykgPC0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJyAKCkRpbVBsb3Qoc2V1LnNjLCBvcmRlciA9IHNhbXBsZS5vcmRlciwgY29scyA9IGNsdXN0LmNvbG91cnMsIHNodWZmbGUgPSBUUlVFLCByYXN0ZXI9RkFMU0UsIHB0LnNpemUgPSAwLjI1LCBsYWJlbCA9IFRSVUUpCgpEaW1QbG90KHNldS5zYywgb3JkZXIgPSBzYW1wbGUub3JkZXIsIGNvbHMgPSBjbHVzdC5jb2xvdXJzLCBzaHVmZmxlID0gVFJVRSwgcmFzdGVyPUZBTFNFLCBwdC5zaXplID0gMC4yNSwgbGFiZWwgPSBGQUxTRSkKCgoKI0lkZW50cyhzZXUuc2MpIDwtICdDZWxsX1N1YnR5cGVzJwojRGltUGxvdChzZXUuc2MsIHNodWZmbGUgPSBUUlVFLCByYXN0ZXI9RkFMU0UsIHB0LnNpemUgPSAwLjI1LCBsYWJlbCA9IFRSVUUpCgoKIyBzYXZlIEZpZ3VyZSA2RAojcGRmKHBhc3RlKG91dHB1dF9wYXRoLCJVTUFQX0NlbGxTdWJ0eXBlTWFya2Vyc09jdDE2LnBkZiIpLHdpZHRoID0gOS40LCBoZWlnaHQgPSAzLjkpCkRpbVBsb3Qoc2V1LnNjLCBvcmRlciA9IHNhbXBsZS5vcmRlciwgY29scyA9IGNsdXN0LmNvbG91cnMsIHNodWZmbGUgPSBUUlVFLCByYXN0ZXI9RkFMU0UsIHB0LnNpemUgPSAwLjI1LCBsYWJlbCA9IEZBTFNFKQojZGV2Lm9mZigpCgoKIyBGaWd1cmUgUzI1CiMgd2l0aCBsYWJlbHMKcGRmKHBhc3RlKG91dHB1dF9wYXRoLCJVTUFQX0NlbGxTdWJ0eXBlTWFya2Vyc0xhYmxlc09jdDE2LnBkZiIpLHdpZHRoID0gMTIsIGhlaWdodCA9IDUpCkRpbVBsb3Qoc2V1LnNjLCBvcmRlciA9IHNhbXBsZS5vcmRlciwgY29scyA9IGNsdXN0LmNvbG91cnMsIHNodWZmbGUgPSBUUlVFLCByYXN0ZXI9RkFMU0UsIHB0LnNpemUgPSAwLjI1LCBsYWJlbCA9IFRSVUUsIHJlcGVsID0gVFJVRSkKZGV2Lm9mZigpCgoKCmBgYAoKCk1ha2UgYSBoZWF0bWFwCgpgYGB7cn0KCiMgc29tZSBEQSBjbGFzc2ljIG1hcmtlcgojIHNvbWUgbmV1cm9uYWwgbWFya2VycwojIHNvbWUgClBEX3BvdWxpbiA9IGMoIlRIIiwiU0xDNkEzIiwiU0xDMThBMiIsIlNPWDYiLCJORE5GIiwiU05DRyIsIkFMREgxQTEiLCJDQUxCMSIsIlRBQ1IyIiwiU0xDMTdBNiIsIlNMQzMyQTEiLCJPVFgyIiwiR1JQIiwiTFBMIiwiQ0NLIiwiVklQIikKCiNsaWtlbHkgdG9vIG1hbnkKZnQgPC0gYygiQ09MM0ExIiwiRkFCUDUiLCJIUEQiLCJSQUIzQiIsIlRQQkciLCJUVFIiLCJTT1gyIiwiQVNDTDEiLCJDUCIsIkdSSUEyIiwKICAgICAgICAiTUdQIiwiU1BBUkNMMSIsIlRQSDEiLCJURlBJMSIsIkNZMUIxIiwiTkVBVDEiLCJQVE4iLCJSUEw0MSIsIlRPUDJBIiwiVkNBTiIpCgojIHRvIGNoYW5nZSB0aGUgY2VsbCB0eXBlIG9yZGVyCklkZW50cyhzZXUuc2MpIDwtICdDZWxsX1N1YnR5cGVfTWFya2VycycKCgoKc2V1LnNjJENlbGxfU3VidHlwZV9NYXJrZXJzIDwtIGZhY3RvcihzZXUuc2MkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsIGxldmVscyA9IHNhbXBsZS5vcmRlcikKCiNzZXUuc2MgPC0gU2NhbGVEYXRhKHNldS5zYykKI0RvSGVhdG1hcChzZXUuc2MsIGZlYXR1cmVzID0gUERfcG91bGluLCBncm91cC5ieSA9ICdDZWxsX1N1YnR5cGVfTWFya2VycycsIHNsb3QgPSAnc2NhbGUuZGF0YScpCkRvdFBsb3Qoc2V1LnNjLCBmZWF0dXJlcyA9IGZ0LCBncm91cC5ieSA9ICdDZWxsX1N1YnR5cGVfTWFya2VycycpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCiMgdGhlc2UgYXJlIG5vdCB2ZXJ5IGhlbHBmdWwgbWFya2VycyAKIyBuZWVkIHRvIHJldmVyc2Ugc2FtcGxlIG9yZGVyIGZvciBoZWF0bWFwcwpEb0hlYXRtYXAoc2V1LnNjLCBmZWF0dXJlcyA9IGZ0LCBncm91cC5ieSA9ICdDZWxsX1N1YnR5cGVfTWFya2VycycpCgpmdCA9IGMoKQoKZmVhdHVyZV9saXN0ID0gYygiUEFYNiIsIk9UWDIiLCJWSU0iLCJTTEMxQTMiLCJTT1gyIiwiSEVTMSIsIk5FUyIsIlMxMDBCIiwiU09YOSIsIk1BUDIiLAogICAgICAgICAgICAgICAgICJOQ0FNMSIsIkNEMjQiLCJHUklBMiIsIkdBQkJSMSIpCgpmZWF0dXJlX2xpc3QgPSBjKCJUSCIsIlBBWDYiLCJPVFgyIiwiTUFQMiIsIk5DQU0xIiwiQ0QyNCIsIkdSSUEyIiwiR0FCQlIxIiwKICAgICAgICAgICAgICAgICAiVklNIiwiU0xDMUEzIiwiU09YMiIsIkhFUzEiLCJORVMiLCJTMTAwQiIsIlNPWDkiLCJHRkFQIgogICAgICAgICAgICAgICAgICkKCiJHUklBMiIsIkdBQkJSMSIKCmZlYXR1cmVfbGlzdCA9IGMoIk1BUDIiLCJOQ0FNMSIsIkNEMjQiLCJHUklBMiIpCgpmZWF0dXJlX2xpc3QgPSBjKCJNQVAyIiwiTkNBTTEiLCJDRDI0IiwiR1JJQTIiLCJHUklOMkIiLCwiR0FEMSIsIkdBRDIiLCJHQUJSQTEiLCJHQUJSQjIiLCJUSCIsIkFMREgxQTEiLCJMTVgxQiIsIk5SNEEyIiwiQ09SSU4iLCJDQUxCMSIsIktDTko2IiwiQ1hDUjQiLCJJVEdBNiIsIlNMQzFBMyIsIkNENDQiLCJBUVA0IiwiUzEwMEIiLCAiUERHRlJBIiwiT0xJRzIiLCJNQlAiLCJDTEROMTEiLCJWQ0FNMSIpCgoiU09YOSIKZmVhdHVyZV9saXN0IDwtIGMoIlJCRk9YMyIsIkdSSU4yQiIsIkdBRDEiLCJHQUQyIiwiR0FCUkExIiwiR0FCUkIyIiwiVEgiKQoKZmVhdHVyZV9saXN0IDwtIGMoIlNMQzFBMyIsICJQQVg2IiwgIlNPWDIiLCAiUERHRkQiLCAiR0xJMyIsICJTVE1OMiIsICJORVVST0Q2IiwgIlZJTSIsICJIRVMxIikKCkRvdFBsb3Qoc2V1LnNjLCBmZWF0dXJlcyA9IGZlYXR1cmVfbGlzdCwgZ3JvdXAuYnkgPSAnQ2VsbF9TdWJ0eXBlX01hcmtlcnMnKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCgojIHRoZXNlIGFyZSBub3QgdmVyeSBoZWxwZnVsIG1hcmtlcnMgCiMgbmVlZCB0byByZXZlcnNlIHNhbXBsZSBvcmRlciBmb3IgaGVhdG1hcHMKRG9IZWF0bWFwKHNldS5zYywgZmVhdHVyZXMgPSBmZWF0dXJlX2xpc3QsIGdyb3VwLmJ5ID0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJykKCgoKCmBgYAoKSGVhdG1hcCBvciBEb3RwbG90IApTYXZlIHBkZgoKCmBgYHtyfQoKCmZlYXR1cmVfbGlzdCA9IGMoIlRIIiwiUEFYNiIsIk9UWDIiLCJNQVAyIiwiTkNBTTEiLCJDRDI0IiwiR1JJQTIiLCJHQUJCUjEiLAogICAgICAgICAgICAgICAgICJWSU0iLCJTTEMxQTMiLCJTT1gyIiwiSEVTMSIsIk5FUyIsIlMxMDBCIiwiU09YOSIKICAgICAgICAgICAgICAgICApCgpmZWF0dXJlX2xpc3QuZCA9IGMoIlBBWDYiLCJWSU0iLCJTTEMxQTMiLCJTT1gyIiwiSEVTMSIsIk5FUyIsIk9UWDIiLAogICAgICAgICAgICAgICAgICJNQVAyIiwiTkNBTTEiLCJDRDI0IiwiR1JJQTIiLCJHQUJCUjEiLCJTMTAwQiIsIlNPWDkiCiAgICAgICAgICAgICAgICAgKQoKCkRvdFBsb3Qoc2V1LnNjLCBmZWF0dXJlcyA9IGZlYXR1cmVfbGlzdC5kLCBncm91cC5ieSA9ICdDZWxsX1N1YnR5cGVfTWFya2VycycpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKCkRvdFBsb3Qoc2V1LnNjLCBmZWF0dXJlcyA9ICJUSCIsIGdyb3VwLmJ5ID0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJykgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQojIHRoZXNlIGFyZSBub3QgdmVyeSBoZWxwZnVsIG1hcmtlcnMgCiMgbmVlZCB0byByZXZlcnNlIHNhbXBsZSBvcmRlciBmb3IgaGVhdG1hcHMKCnNhbXBsZS5vcmRlci5yIDwtIHJldihzYW1wbGUub3JkZXIpCgpzZXUuc2MkQ2VsbF9TdWJ0eXBlX01hcmtlcnMgPC0gZmFjdG9yKHNldS5zYyRDZWxsX1N1YnR5cGVfTWFya2VycywgbGV2ZWxzID0gc2FtcGxlLm9yZGVyLnIpCgoKIyBzYXZlIHRoZSBkb3RwbG90cwpwZGYocGFzdGUob3V0cHV0X3BhdGgsIkRvdFBsb3RDZWxsU3VidHlwZXNPY3QxNy5wZGYiKSkKRG90UGxvdChzZXUuc2MsIGZlYXR1cmVzID0gZmVhdHVyZV9saXN0LmQsIGdyb3VwLmJ5ID0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJykgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQpkZXYub2ZmKCkKCnBkZihwYXN0ZShvdXRwdXRfcGF0aCwiRG90UGxvdFRIYnlzdWJ0eXBlc09jdDE3LnBkZiIpKQpEb3RQbG90KHNldS5zYywgZmVhdHVyZXMgPSAiVEgiLCBncm91cC5ieSA9ICdDZWxsX1N1YnR5cGVfTWFya2VycycpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKZGV2Lm9mZigpCgpgYGAKCnNhdmUgdGhlIGhlYXRtYXAKQ2hhbmdlIHRoZSBjb2xvdXJzCgpgYGB7cn0KCmZlYXR1cmVfbGlzdCA9IGMoIlRIIiwiUEFYNiIsIk9UWDIiLCJNQVAyIiwiTkNBTTEiLCJDRDI0IiwiR1JJQTIiLCJHQUJCUjEiLAogICAgICAgICAgICAgICAgICJWSU0iLCJTTEMxQTMiLCJTT1gyIiwiSEVTMSIsIk5FUyIsIlMxMDBCIiwiU09YOSIKICAgICAgICAgICAgICAgICApCgojIHJldmVyc2UgdGhlIGNlbGwgdHlwZSBvcmRlcgpzYW1wbGUub3JkZXIuciA8LSByZXYoc2FtcGxlLm9yZGVyKQoKc2V1LnNjJENlbGxfU3VidHlwZV9NYXJrZXJzIDwtIGZhY3RvcihzZXUuc2MkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsIGxldmVscyA9IHNhbXBsZS5vcmRlci5yKQoKcGRmKHBhc3RlKG91dHB1dF9wYXRoLCJIZWF0TWFwc3VidHlwZXNPY3QxNy5wZGYiLHNlcCA9ICIiKSx3aWR0aCA9IDExLCBoZWlnaHQgPSA1KQpEb0hlYXRtYXAoc2V1LnNjLCBmZWF0dXJlcyA9IGZlYXR1cmVfbGlzdCwgZ3JvdXAuYnkgPSAnQ2VsbF9TdWJ0eXBlX01hcmtlcnMnLCBncm91cC5jb2xvcnMgPSBjbHVzdC5jb2xvdXJzLCBkaXNwLm1heCA9IDIsIGRpc3AubWluID0gLTEuNSwKICAgICAgICAgIGFuZ2xlID0gOTApICsgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3JzID0gYygiIzE1NGM3OSIsICIjZWVlZWU0IiwgIiNlMjg3NDMiKSkgKyAKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKQpkZXYub2ZmKCkKCgpgYGAKCgpTdWJ0eXBlIG1hcmtlcnMKCgpgYGB7cn0KSWRlbnRzKHNldS5zYykgPC0gJ0NlbGxfU3VidHlwZXMnCm5ldXJvbnMgPC0gc3Vic2V0KHNldS5zYywgaWRlbnRzID0gYygiTmV1cm9uczEiLCJOZXVyb25zMiIsIk5ldXJvbnMzIiwiTmV1cm9uczQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ldXJvbnM1IiwiTmV1cm9uczYiLCJOZXVyb25zNyIpKQoKSWRlbnRzKG5ldXJvbnMpIDwtICdDZWxsX1N1YnR5cGVfTWFya2VycycKCnBkZihwYXN0ZShvdXRwdXRfcGF0aCwiVU1BUF9OZXVyb25zT2N0MTcucGRmIixzZXAgPSAiIiksd2lkdGggPSA3LCBoZWlnaHQgPSA0KQpEaW1QbG90KG5ldXJvbnMpICsgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgY29sb3VyID0gImJsYWNrIikpCmRldi5vZmYoKQoKSWRlbnRzKHNldS5zYykgPC0gJ0NlbGxfU3VidHlwZXMnCm5ldXJvbnMuZGEgPC0gc3Vic2V0KHNldS5zYywgaWRlbnRzID0gYygiREFOZXVyb25zMSIsIkRBTmV1cm9uczIiLCJEQU5ldXJvbnMzIikpCgpJZGVudHMobmV1cm9ucy5kYSkgPC0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJwpwZGYocGFzdGUob3V0cHV0X3BhdGgsIlVNQVBfREFOZXVyb25zT2N0MTcucGRmIixzZXAgPSAiIiksd2lkdGggPSA3LCBoZWlnaHQgPSA0KQpEaW1QbG90KG5ldXJvbnMuZGEpKyAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBjb2xvdXIgPSAiYmxhY2siKSkKZGV2Lm9mZigpCgpJZGVudHMoc2V1LnNjKSA8LSAnQ2VsbF9TdWJ0eXBlcycKYXN0cm8gPC0gc3Vic2V0KHNldS5zYywgaWRlbnRzID0gYygiQXN0cm9jeXRlczEiLCJBc3Ryb2N5dGVzMiIsIkFzdHJvY3l0ZXMzIikpCklkZW50cyhhc3RybykgPC0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJwpwZGYocGFzdGUob3V0cHV0X3BhdGgsIlVNQVBfQXN0cm9PY3QxNy5wZGYiLHNlcCA9ICIiKSx3aWR0aCA9IDcsIGhlaWdodCA9IDQpCkRpbVBsb3QoYXN0cm8pKyAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBjb2xvdXIgPSAiYmxhY2siKSkKZGV2Lm9mZigpCgpJZGVudHMoc2V1LnNjKSA8LSAnQ2VsbF9TdWJ0eXBlcycKcmcgPC0gc3Vic2V0KHNldS5zYywgaWRlbnRzID0gYygiUmFkaWFsR2xpYTEiLCJSYWRpYWxHbGlhMiIsIlJhZGlhbEdsaWEzIiwiUmFkaWFsR2xpYTQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSYWRpYWxHbGlhNSIsIlJhZGlhbEdsaWE2IikpCklkZW50cyhyZykgPC0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJwpwZGYocGFzdGUob3V0cHV0X3BhdGgsIlVNQVBfUkdPY3QxNy5wZGYiLHNlcCA9ICIiKSx3aWR0aCA9IDcsIGhlaWdodCA9IDQpCkRpbVBsb3QocmcpKyAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBjb2xvdXIgPSAiYmxhY2siKSkKZGV2Lm9mZigpCgoKCgpgYGAKCgpEb3RQbG90cyBvZiBtYXJrZXJzIGluIGNlbGwgdHlwZSBzdWJzZXRzCgpgYGB7cn0KCm4ubWFya2VycyA8LSBjKCJBU0NMMSIsIkNQIiwiR1JJQTIiLCJNR1AiLCJTUEFSQ0wxIiwiVFBIMSIsIlRGUEkyIiwiQ0QyNCIpCgpwZGYocGFzdGUob3V0cHV0X3BhdGgsIkRvdHBsb3RfTmV1U3ViTWFya2Vyc09jdDE3LnBkZiIsc2VwID0gIiIpLHdpZHRoID0gNywgaGVpZ2h0ID0gNCkKRG90UGxvdChuZXVyb25zLCBmZWF0dXJlcyA9IG4ubWFya2VycykgKyAKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTYsIGNvbG91ciA9ICJibGFjayIpLGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKQpkZXYub2ZmKCkKCmRhLm1hcmtlcnMgPC0gYygiUkFCM0IiLCJUUEJHIiwiVFRSIiwiVEgiLCJTT1g2IiwiQ0FMQjEiLCJTTEMxN0E2IikKCnBkZihwYXN0ZShvdXRwdXRfcGF0aCwiRG90cGxvdF9EQU5ldVN1Yk1hcmtlcnNPY3QxNy5wZGYiLHNlcCA9ICIiKSx3aWR0aCA9IDcsIGhlaWdodCA9IDQpCkRvdFBsb3QobmV1cm9ucy5kYSwgZmVhdHVyZXMgPSBkYS5tYXJrZXJzKSArIAogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgY29sb3VyID0gImJsYWNrIiksYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCmRldi5vZmYoKQoKcmcubWFya2VycyA8LSBjKCJDWVAxQjEiLCJORUFUMSIsIlBUTiIsIlJQTDQxIiwiVE9QMkEiLCJWQ0FOIiwiU09YMiIsIlNMSVQyIiwiSEVTMSIsIlZJTSIpCgpwZGYocGFzdGUob3V0cHV0X3BhdGgsIkRvdHBsb3RfUkdNYXJrZXJzT2N0MTcucGRmIixzZXAgPSAiIiksd2lkdGggPSA3LCBoZWlnaHQgPSA0KQpEb3RQbG90KHJnLCBmZWF0dXJlcyA9IHJnLm1hcmtlcnMpICsgCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBjb2xvdXIgPSAiYmxhY2siKSxheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKZGV2Lm9mZigpCgojIEFwb2UsIEdmYXAsIEFxcDQgYW5kIFNsYzFhMwphc3Ryby5tYXJrZXJzIDwtIGMoIkNPTDNBMSIsIkZBQlA1IiwiSFBEIiwiQVBPRSIsIlMxMDBCIiwiSUdGQlAyIiwiREJJIiwKICAgICAgICAgICAgICAgICAgICJQUlNTNTYiLCAiSUdUUCIsIkxGSVQzIiwiTElHUDEiLAogICAgICAgICAgICAgICAgICAgIkNPTDFBMiIpCgpwZGYocGFzdGUob3V0cHV0X3BhdGgsIkRvdHBsb3RfQXN0cm9NYXJrZXJzT2N0MTcucGRmIixzZXAgPSAiIiksd2lkdGggPSA3LCBoZWlnaHQgPSA0KQpEb3RQbG90KGFzdHJvLCBmZWF0dXJlcyA9IGFzdHJvLm1hcmtlcnMpICsgCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBjb2xvdXIgPSAiYmxhY2siKSxheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkKZGV2Lm9mZigpCgoKYGBgCgpNYWtlIGEgbGFiZWwgbGV2ZWwgb2YgbWFpbiBjZWxsIHR5cGVzIGZyb20gdGhlIG1lcmdlIGRhdGEKCmBgYHtyfQoKdW5pcXVlKHNldS5zYyRDZWxsX1N1YnR5cGVfTWFya2VycykKSWRlbnRzKHNldS5zYykgPC0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJwoKY2x1c3Rlci5pZHMgPC0gYygiQXN0cm9jeXRlcyIsIk5ldXJvbnMiLCJSYWRpYWxHbGlhIiwiTmV1cm9ucyIsCiAgICAgICAgICAgICAgICAgIkFzdHJvY3l0ZXMiLCJOZXVyb25zIiwiUmFkaWFsR2xpYSIsIk5ldXJvbnMiLAogICAgICAgICAgICAgICAgICJBc3Ryb2N5dGVzIiwiTmV1cm9ucyIsIlJhZGlhbEdsaWEiLAogICAgICAgICAgICAgICAgICJEQU5ldXJvbnMiLCJOZXVyb25zIiwiTWl4IiwiTlBDIiwKICAgICAgICAgICAgICAgICAiTmV1cm9ucyIsIkRBTmV1cm9ucyIsIkRBTmV1cm9ucyIsCiAgICAgICAgICAgICAgICAgIlJhZGlhbEdsaWEiLCJSYWRpYWxHbGlhIiwiUmFkaWFsR2xpYSIKICAgICAgICAgICAgICAgICApCgoKbmFtZXMoY2x1c3Rlci5pZHMpIDwtIGxldmVscyhzZXUuc2MpCnNldS5zYyA8LSBSZW5hbWVJZGVudHMoc2V1LnNjLCBjbHVzdGVyLmlkcykKc2V1LnNjJENlbGxfVHlwZTIgPC0gSWRlbnRzKHNldS5zYykKSWRlbnRzKHNldS5zYykgPC0gJ0NlbGxfVHlwZTInCkRpbVBsb3Qoc2V1LnNjKQoKRGltUGxvdChzZXUuc2MsIGdyb3VwLmJ5ID0gJ0NlbGxfU3VidHlwZV9NYXJrZXJzJykKRGltUGxvdChzZXUuc2MsIGdyb3VwLmJ5ID0gJ0NlbGxfU3VidHlwZXMnKQpEaW1QbG90KHNldS5zYywgZ3JvdXAuYnkgPSAnQ2VsbF9UeXBlMicpCgoKYGBgCgoKYGBge3J9CgojIG9yaWdpbmFsIGNsdXN0ZXJzIHByb3BvcnRpb24gb2YgY2VsbCB0eXBlcyBpbiAKbGlicmFyeShyZXNoYXBlMikKCnByLmNlbGx0eXBlcyA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKHNldS5zYyRvcmlnLmlkZW50LHNldS5zYyRDZWxsX1R5cGUyKSkKcHIuY2VsbHR5cGVzIDwtIHJlc2hhcGUocHIuY2VsbHR5cGVzLCBpZHZhciA9ICJWYXIyIiwgdGltZXZhciA9ICJWYXIxIiwgZGlyZWN0aW9uID0gIndpZGUiKQpwci5jZWxsdHlwZXMKCnRhYmxlKHNldS5zYyRDZWxsX1R5cGUyKQoKd3JpdGUuY3N2KHByLmNlbGx0eXBlcywgcGFzdGUob3V0cHV0X3BhdGgsIkZyZXFDZWxsVHlwZXMyaW5GQUNTLmNzdiIpKQoKYGBgCgoKClByb3BvcnRpb24gb2YgY2VsbCB0eXBlcyBpbiBvcmlnaW5hbCBGQUNTIHBvcHVsYXRpb25zCgoKYGBge3J9CgojIG9yaWdpbmFsIGNsdXN0ZXJzIHByb3BvcnRpb24gb2YgY2VsbCB0eXBlcyBpbiAKbGlicmFyeShyZXNoYXBlMikKCnByLmNlbGx0eXBlcyA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKG5ldXJvbnMuZGEkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsbmV1cm9ucy5kYSRvcmlnLmlkZW50KSkKcHIuY2VsbHR5cGVzIDwtIHJlc2hhcGUocHIuY2VsbHR5cGVzLCBpZHZhciA9ICJWYXIyIiwgdGltZXZhciA9ICJWYXIxIiwgZGlyZWN0aW9uID0gIndpZGUiKQpwci5jZWxsdHlwZXMKcHIgPC0gcHIuY2VsbHR5cGVzICU+JSBzZWxlY3QoVmFyMixgRnJlcS5EQU5ldXJvbnMtUkFCM0JgLGBGcmVxLkRBTmV1cm9ucy1UUEJHYCxgRnJlcS5EQU5ldXJvbnMtVFRSYCkKcHIKcHIgPC0gdChwcikKcHIKd3JpdGUuY3N2KHByLCBwYXN0ZShvdXRwdXRfcGF0aCwiQ2VsbENvdW50c0RBbmV1cm9uc1BlckZBQ1Nwb3AuY3N2IikpCgoKYGBgCgoKUHJvcG9ydGlvbiBvZiBjZWxsIHR5cGVzIHRlc3RzCgpgYGB7cn0KCmxpYnJhcnkoInNjUHJvcG9ydGlvblRlc3QiKQoKcHJvcF90ZXN0IDwtIHNjX3V0aWxzKHNldS5zYykKCnByb3BfdGVzdCA8LSBwZXJtdXRhdGlvbl90ZXN0KAoJcHJvcF90ZXN0LCBjbHVzdGVyX2lkZW50aXR5ID0gIkNlbGxfVHlwZTIiLAoJc2FtcGxlXzEgPSAiTmV1cm9uczEiLCBzYW1wbGVfMiA9ICJOZXVyb25zMiIsCglzYW1wbGVfaWRlbnRpdHkgPSAib3JpZy5pZGVudCIKKQoKCnBlcm11dGF0aW9uX3Bsb3QocHJvcF90ZXN0KQoKcHJvcF90ZXN0IDwtIHBlcm11dGF0aW9uX3Rlc3QoCglwcm9wX3Rlc3QsIGNsdXN0ZXJfaWRlbnRpdHkgPSAiQ2VsbF9UeXBlMiIsCglzYW1wbGVfMSA9ICJOZXVyb25zMSIsIHNhbXBsZV8yID0gIlJhZGlhbEdsaWEiLAoJc2FtcGxlX2lkZW50aXR5ID0gIm9yaWcuaWRlbnQiCikKcGVybXV0YXRpb25fcGxvdChwcm9wX3Rlc3QpCgoKcHJvcF90ZXN0IDwtIHBlcm11dGF0aW9uX3Rlc3QoCglwcm9wX3Rlc3QsIGNsdXN0ZXJfaWRlbnRpdHkgPSAiQ2VsbF9UeXBlMiIsCglzYW1wbGVfMSA9ICJOZXVyb25zMiIsIHNhbXBsZV8yID0gIlJhZGlhbEdsaWEiLAoJc2FtcGxlX2lkZW50aXR5ID0gIm9yaWcuaWRlbnQiCikKcGVybXV0YXRpb25fcGxvdChwcm9wX3Rlc3QpCgoKcHJvcF90ZXN0IDwtIHBlcm11dGF0aW9uX3Rlc3QoCglwcm9wX3Rlc3QsIGNsdXN0ZXJfaWRlbnRpdHkgPSAiQ2VsbF9UeXBlMiIsCglzYW1wbGVfMSA9ICJBc3Ryb2N5dGVzIiwgc2FtcGxlXzIgPSAiUmFkaWFsR2xpYSIsCglzYW1wbGVfaWRlbnRpdHkgPSAib3JpZy5pZGVudCIKKQpwZXJtdXRhdGlvbl9wbG90KHByb3BfdGVzdCkKCmBgYAoKCkNoZWNrIHRoZSBwcm9wb3J0aW9ucyBvZiBzdWJ0eXBlcyBvZiBEQSBuZXVyb25zCgpgYGB7cn0KCiNsaWJyYXJ5KCJzY1Byb3BvcnRpb25UZXN0IikKCnByb3BfdGVzdCA8LSBzY191dGlscyhuZXVyb25zLmRhKQoKcHJvcF90ZXN0IDwtIHBlcm11dGF0aW9uX3Rlc3QoCglwcm9wX3Rlc3QsIGNsdXN0ZXJfaWRlbnRpdHkgPSAiQ2VsbF9TdWJ0eXBlX01hcmtlcnMiLAoJc2FtcGxlXzEgPSAiTmV1cm9uczEiLCBzYW1wbGVfMiA9ICJOZXVyb25zMiIsCglzYW1wbGVfaWRlbnRpdHkgPSAib3JpZy5pZGVudCIKKQoKCnBlcm11dGF0aW9uX3Bsb3QocHJvcF90ZXN0KQoKYGBgCgoKRGlmZmVyZW50aWFsIGdlbmUgZXhwcmVzc2lvbiBiZXR3ZWVuIE5ldXJvbnMxIGFuZCBOZXVyb25zMiBmb3IgT3RoZXIgbmV1cm9ucyBhbmQgREEgbmV1cm9ucy4gCgpgYGB7cn0KSWRlbnRzKHNldS5zYykgPC0gJ0NlbGxfVHlwZTInCnN1Yi5uZXVyIDwtIHN1YnNldChzZXUuc2MsIGlkZW50cyA9ICJOZXVyb25zIikKRGltUGxvdChzdWIubmV1ciwgZ3JvdXAuYnkgPSAnQ2VsbF9TdWJ0eXBlX01hcmtlcnMnKQoKSWRlbnRzKHN1Yi5uZXVyKSA8LSAnb3JpZy5pZGVudCcKZGVnLm5ldXJvbnMgPC0gRmluZE1hcmtlcnMoc3ViLm5ldXIsIGlkZW50LjEgPSAiTmV1cm9uczEiLCBpZGVudC4yID0gIk5ldXJvbnMyIikKCnVwIDwtIHJvd25hbWVzKGRlZy5uZXVyb25zICU+JSBmaWx0ZXIoYXZnX2xvZzJGQyA+IDEuMikpCmxlbmd0aCh1cCkKCmRvd24gPC0gcm93bmFtZXMoZGVnLm5ldXJvbnMgJT4lIGZpbHRlcihhdmdfbG9nMkZDIDwgLTYpKQpsZW5ndGgoZG93bikKCnVwLmRvd24gPC0gYyh1cCxkb3duKQoKRG9IZWF0bWFwKHN1Yi5uZXVyLCBncm91cC5ieSA9ICdvcmlnLmlkZW50JywgZmVhdHVyZXMgPSB1cC5kb3duKQoKdXAKZG93bgoKCiMgdXAgaXMgaW4gbmV1cm9uczEgYW5kIGRvd24gaXMgaW4gbmV1cm9uczIKCndyaXRlLmNzdihkZWcubmV1cm9ucywgcGFzdGUob3V0cHV0X3BhdGgsICJERUcubmV1cm9uczF2c25ldXJvbnMyaW5OZXVyb25zLmNzdiIpKQoKCmBgYAoKCgpJbiBEQSBuZXVyb25zCgpgYGB7cn0KCklkZW50cyhzZXUuc2MpIDwtICdDZWxsX1R5cGUyJwpzdWIubmV1ciA8LSBzdWJzZXQoc2V1LnNjLCBpZGVudHMgPSAiREFOZXVyb25zIikKRGltUGxvdChzdWIubmV1ciwgZ3JvdXAuYnkgPSAnQ2VsbF9TdWJ0eXBlX01hcmtlcnMnKQoKSWRlbnRzKHN1Yi5uZXVyKSA8LSAnb3JpZy5pZGVudCcKZGVnLm5ldXJvbnMuZGEgPC0gRmluZE1hcmtlcnMoc3ViLm5ldXIsIGlkZW50LjEgPSAiTmV1cm9uczEiLCBpZGVudC4yID0gIk5ldXJvbnMyIikKCnVwIDwtIHJvd25hbWVzKGRlZy5uZXVyb25zICU+JSBmaWx0ZXIoYXZnX2xvZzJGQyA+IDEuMikpCmxlbmd0aCh1cCkKCmRvd24gPC0gcm93bmFtZXMoZGVnLm5ldXJvbnMgJT4lIGZpbHRlcihhdmdfbG9nMkZDIDwgLTAuNSkpCmxlbmd0aChkb3duKQpkb3duCmRvd24gPC0gZG93blsxNzozNl0KdXAuZG93biA8LSBjKHVwLGRvd24pCgpEb0hlYXRtYXAoc3ViLm5ldXIsIGdyb3VwLmJ5ID0gJ29yaWcuaWRlbnQnLCBmZWF0dXJlcyA9IHVwLmRvd24pCgpEb3RQbG90KHN1Yi5uZXVyLCBncm91cC5ieSA9ICdvcmlnLmlkZW50JywgZmVhdHVyZXMgPSB1cC5kb3duKSArIFJvdGF0ZWRBeGlzKCkKCndyaXRlLmNzdihkZWcubmV1cm9ucy5kYSwgcGFzdGUob3V0cHV0X3BhdGgsICJERUcubmV1cm9uczF2c25ldXJvbnMyaW5EQU5ldXJvbnMuY3N2IikpCgoKYGBgCgoKTG9vayBhdCB0aGUgR08gYW5kIG90aGVyIHBhdGh3YXkgYW5hbHlzaXMgZm9yIHRoZSBER0UKCmBgYHtyfQoKIyBmb3IgbmV1cm9ucwoKbGlicmFyeShlbnJpY2hSKQoKc2V0RW5yaWNoclNpdGUoIkVucmljaHIiKSAjIEh1bWFuIGdlbmVzCiMgbGlzdCBvZiBhbGwgdGhlIGRhdGFiYXNlcwoKIyBsaWJhcmllcyB3aXRoIGNlbGwgdHlwZXMKI2RicyA8LSBsaXN0RW5yaWNockRicygpCiNkYnMKZGIgPC0gYygnR09fQ2VsbHVsYXJfQ29tcG9uZW50XzIwMTgnLCdHT19CaW9sb2dpY2FsX1Byb2Nlc3NfMjAxOCcsCiAgICAgICAgJ0dPX01vbGVjdWxhcl9GdW5jdGlvbl8yMDE4JykKCk5ldXJvbnMxLnVwIDwtIGRlZy5uZXVyb25zICU+JSBmaWx0ZXIocF92YWxfYWRqIDwgMC4wNSAmIGF2Z19sb2cyRkMgPiAwKQpnZW5lcyA8LSByb3duYW1lcyhOZXVyb25zMS51cCkKCkVyIDwtIGVucmljaHIoZ2VuZXMsIGRhdGFiYXNlcyA9IGRiKQpwcmludChwbG90RW5yaWNoKEVyW1sxXV0sIHNob3dUZXJtcyA9IDIwLCBudW1DaGFyID0gNDAsIHkgPSAiQ291bnQiLCBvcmRlckJ5ID0gIlAudmFsdWUiKSkKcHJpbnQocGxvdEVucmljaChFcltbMl1dLCBzaG93VGVybXMgPSAyMCwgbnVtQ2hhciA9IDQwLCB5ID0gIkNvdW50Iiwgb3JkZXJCeSA9ICJQLnZhbHVlIikpCnByaW50KHBsb3RFbnJpY2goRXJbWzNdXSwgc2hvd1Rlcm1zID0gMjAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiUC52YWx1ZSIpKQoKbGlicmFyeShkcGx5cikKdC5HT2NlbGwubiA8LSBFcltbMV1dIAp0LkdPYmlvLm4gPC0gRXJbWzJdXSAKdC5HT21vbC5uIDwtIEVyW1szXV0gCiMgc3lucGF0aGV0aWMgbmV1cnZvdXMgc3l0ZW0gZGV2CiMgCUZaRDM7Q1ROTkIxO1NPWDExO0FTQ0wxO1NPWDQKI25lZ2F0aXZlIHJlZ3VsYXRpb24gb2YgbmV1cm9uIGRpZmZlcmVudGlhdGlvbiAoR086MDA0NTY2NSkKIyAJRUZOQjI7SUQyO0lEMTtJRDM7SEVTMTtTT1g5O0NBTFI7QVNDTDEKCiMgbmVnYXRpdmUgcmVndWxhdGlvbiBvZiBuZXVyb2dlbmVzaXMgKEdPOjAwNTA3NjgpCiMgSUQyO0lEMTtJRDM7UEFYNjtDQUxSO0FTQ0wxCgojIG5ldXJvbmFsIGRpZmZlcmVudGlhdGlvbgojIAlGWkQzO0lEMjtJRDE7SUQzO0NUTk5CMTtTT1gxMTtPVFgyO1BBWDY7QVNDTDE7U09YNAoKIyAJSUQyO0lEMTtJRDM7U09YMTE7VENGNDtDQUxSO0FTQ0wxCgoKTmV1cm9uczIudXAgPC0gZGVnLm5ldXJvbnMgJT4lIGZpbHRlcihwX3ZhbF9hZGogPCAwLjA1ICYgYXZnX2xvZzJGQyA8IDApCmdlbmVzIDwtIHJvd25hbWVzKE5ldXJvbnMyLnVwKQoKRXIgPC0gZW5yaWNocihnZW5lcywgZGF0YWJhc2VzID0gZGIpCnByaW50KHBsb3RFbnJpY2goRXJbWzFdXSwgc2hvd1Rlcm1zID0gMjAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiUC52YWx1ZSIpKQpwcmludChwbG90RW5yaWNoKEVyW1syXV0sIHNob3dUZXJtcyA9IDIwLCBudW1DaGFyID0gNDAsIHkgPSAiQ291bnQiLCBvcmRlckJ5ID0gIlAudmFsdWUiKSkKcHJpbnQocGxvdEVucmljaChFcltbM11dLCBzaG93VGVybXMgPSAyMCwgbnVtQ2hhciA9IDQwLCB5ID0gIkNvdW50Iiwgb3JkZXJCeSA9ICJQLnZhbHVlIikpCgoKdC5HT2NlbGwuZCA8LSBFcltbMV1dICMlPiUgc2VsZWN0KFRlcm0sIEdlbmVzLCBDb21iaW5lZC5TY29yZSkKdC5HT2Jpby5kIDwtIEVyW1syXV0gIyU+JSBzZWxlY3QoVGVybSwgR2VuZXMsIENvbWJpbmVkLlNjb3JlKQp0LkdPbW9sLmQgPC0gRXJbWzNdXSAjJT4lIHNlbGVjdChUZXJtLCBHZW5lcywgQ29tYmluZWQuU2NvcmUpCiAKCiMgZ28gYmlvbG9naWNhbCB0ZXJtcyBhcmUgdGhlIG1vc3QgaW50ZXJlc3RpbmcgCiAgCiAgCiAgIyBuZXVyb25zMiB1cCAKICAjCiAgCiAgCiAgCgoKCmBgYAoKRm9yIERBIG5ldXJvbnMgCgpgYGB7cn0KCnNldEVucmljaHJTaXRlKCJFbnJpY2hyIikgIyBIdW1hbiBnZW5lcwojIGxpc3Qgb2YgYWxsIHRoZSBkYXRhYmFzZXMKCiMgbGliYXJpZXMgd2l0aCBjZWxsIHR5cGVzCiNkYnMgPC0gbGlzdEVucmljaHJEYnMoKQojZGJzCmRiIDwtIGMoJ0dPX0NlbGx1bGFyX0NvbXBvbmVudF8yMDE4JywnR09fQmlvbG9naWNhbF9Qcm9jZXNzXzIwMTgnLAogICAgICAgICdHT19Nb2xlY3VsYXJfRnVuY3Rpb25fMjAxOCcpCgpOZXVyb25zMS51cCA8LSBkZWcubmV1cm9ucyAlPiUgZmlsdGVyKHBfdmFsX2FkaiA8IDAuMDUgJiBhdmdfbG9nMkZDID4gMCkKZ2VuZXMgPC0gcm93bmFtZXMoTmV1cm9uczEudXApCgpFciA8LSBlbnJpY2hyKGdlbmVzLCBkYXRhYmFzZXMgPSBkYikKcHJpbnQocGxvdEVucmljaChFcltbMl1dLCBzaG93VGVybXMgPSAyMCwgbnVtQ2hhciA9IDQwLCB5ID0gIkNvdW50Iiwgb3JkZXJCeSA9ICJPZGRzLlJhdGlvIikpCnByaW50KHBsb3RFbnJpY2goRXJbWzJdXSwgc2hvd1Rlcm1zID0gMjAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiQWp1c3RlZC5QLnZhbHVlIikpCnByaW50KHBsb3RFbnJpY2goRXJbWzJdXSwgc2hvd1Rlcm1zID0gMjAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiQ29tYmluZWQuU2NvcmUiKSkKCgp0LkdPYmlvLmRhMSA8LSBFcltbMl1dIAoKcGxvdEVucmljaCh0LkdPYmlvLmRhMSwgc2hvd1Rlcm1zID0gMTAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiQ29tYmluZWQuU2NvcmUiKQpwbG90RW5yaWNoKHQuR09iaW8uZGExLCBzaG93VGVybXMgPSAxMCwgbnVtQ2hhciA9IDQwLCB5ID0gIkNvdW50Iiwgb3JkZXJCeSA9ICJPdmVybGFwIikKCiMgCUVGTkIyO0lEMjtJRDE7SUQzO0hFUzE7U09YOTtDQUxSO0FTQ0wxCiMgbmV1cm9uYWwgZGlmZmVyZW50aWF0aW9uCiMgCUZaRDM7SUQyO0lEMTtJRDM7Q1ROTkIxO1NPWDExO09UWDI7UEFYNjtBU0NMMTtTT1g0Ck5ldXJvbnMyLnVwIDwtIGRlZy5uZXVyb25zICU+JSBmaWx0ZXIocF92YWxfYWRqIDwgMC4wNSAmIGF2Z19sb2cyRkMgPCAwKQpnZW5lcyA8LSByb3duYW1lcyhOZXVyb25zMi51cCkKCkVyIDwtIGVucmljaHIoZ2VuZXMsIGRhdGFiYXNlcyA9IGRiKQpwcmludChwbG90RW5yaWNoKEVyW1syXV0sIHNob3dUZXJtcyA9IDIwLCBudW1DaGFyID0gNDAsIHkgPSAiQ291bnQiLCBvcmRlckJ5ID0gIk9kZHMuUmF0aW8iKSkKcHJpbnQocGxvdEVucmljaChFcltbMl1dLCBzaG93VGVybXMgPSAyMCwgbnVtQ2hhciA9IDQwLCB5ID0gIkNvdW50Iiwgb3JkZXJCeSA9ICJQLnZhbHVlIikpCnByaW50KHBsb3RFbnJpY2goRXJbWzJdXSwgc2hvd1Rlcm1zID0gMjAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiQ29tYmluZWQuU2NvcmUiKSkKdC5HT2Jpby5kYTIgPC0gRXJbWzJdXSAKCiMgbWFueSBNVCBnZW5lLCBhbHNvICJGVEgxIiwiRlRMIiwiQVBPRSIsIlNBVDEiLCJQVE4iLCJHQUJBUkFQIiwiUFRHRFMiCgpwZGYocGFzdGUob3V0cHV0X3BhdGgsIkdPcmVzdWx0ZXNOZXVyb25zMXZzMi5wZGYiKSwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNikKcGxvdEVucmljaCh0LkdPYmlvLmRhMSwgc2hvd1Rlcm1zID0gMTAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiQ29tYmluZWQuU2NvcmUiKSArCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBjb2xvdXIgPSAiYmxhY2siKSkKcGxvdEVucmljaCh0LkdPYmlvLmRhMSwgc2hvd1Rlcm1zID0gMTAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiT3ZlcmxhcCIpKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgY29sb3VyID0gImJsYWNrIikpCnBsb3RFbnJpY2godC5HT2Jpby5kYTIsIHNob3dUZXJtcyA9IDEwLCBudW1DaGFyID0gNDAsIHkgPSAiQ291bnQiLCBvcmRlckJ5ID0gIkNvbWJpbmVkLlNjb3JlIikrCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE2LCBjb2xvdXIgPSAiYmxhY2siKSkKcGxvdEVucmljaCh0LkdPYmlvLmRhMiwgc2hvd1Rlcm1zID0gMTAsIG51bUNoYXIgPSA0MCwgeSA9ICJDb3VudCIsIG9yZGVyQnkgPSAiT3ZlcmxhcCIpKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiwgY29sb3VyID0gImJsYWNrIikpCmRldi5vZmYoKQoKCmBgYAoKCkRvdCBwbG90cyBvZiBzb21lIHVwIHJlZ3VsYXRlZCBnZW5lcwoKYGBge3J9CgpJZGVudHMoc2V1LnNjKSA8LSAnQ2VsbF9UeXBlMicKYWxsLm5ldXJvbnMgPC0gc3Vic2V0KHNldS5zYyxpZGVudHMgPSBjKCJEQU5ldXJvbnMiLCJOZXVyb25zIikgKQoKSWRlbnRzKGFsbC5uZXVyb25zKSA8LSAnb3JpZy5pZGVudCcKYWxsLm5ldXJvbnMgPC0gc3Vic2V0KGFsbC5uZXVyb25zLGlkZW50cyA9IGMoIk5ldXJvbnMxIiwiTmV1cm9uczIiKSApCgojIAlGWkQzO0lEMjtJRDE7SUQzO0NUTk5CMTtTT1gxMTtPVFgyO1BBWDY7QVNDTDE7U09YNAoKcmVndWxhdGUuZ2VuZXMgPC0gYygiRlpEMyIsIkNUTk5CMSIsIlNPWDExIiwiQVNDTDEiLCJTT1g0IiwiSUQyIiwiSUQxIiwiSUQzIiwKICAgICAgICAgICAgICAgICAgICAiVENGNCIsIkNBTFIiLCJPVFgyIiwiUEFYNiIsIkhFUzEiLCJTT1g5IikKCiMgbWFya2VycyB1cCBpbiBuZXVyb25zMSAtIHdpdGggY2hhbmdlIGluIGJvdGggREEgYW5kIG90aGVyIG5ldXJvbnMKcmVndWxhdGUuZ2VuZXMgPC0gYygiRlpEMyIsIkNUTk5CMSIsIlNPWDExIiwiQVNDTDEiLCJTT1g0IiwKICAgICAgICAgICAgICAgICAgICAiVENGNCIsIkNBTFIiLCJPVFgyIiwiUEFYNiIsIkVGTkIyIiwgCiAgICAgICAgICAgICAgICAgICAgIkNEMjQiLCJLQ05RMU9UMSIsIkNDTkcyIiwiSEVTNiIpCgojIHRvcCB1cCBpbiBuZXVyb25zIDEgCiMgIkNEMjQiICAgICAiS0NOUTFPVDEiICJDQ05HMiIgICAgIkFTQ0wxIiAgICAiSEVTNiIgCgojIHNlbGVjdGVkIHVwIHJlZ3VsYXRlZCBpbiBOZXVyb25zIDEKcmVndWxhdGUuZ2VuZXMgPC0gYygiRlpEMyIsIkFTQ0wxIiwiU09YNCIsCiAgICAgICAgICAgICAgICAgICAgIlRDRjQiLCJDQUxSIiwiUEFYNiIsIAogICAgICAgICAgICAgICAgICAgICJDRDI0IiwiS0NOUTFPVDEiLCJDQ05HMiIpCgpEb3RQbG90KGFsbC5uZXVyb25zLCBncm91cC5ieSA9ICdvcmlnLmlkZW50JywgZmVhdHVyZXMgPSByZWd1bGF0ZS5nZW5lcywKICAgICAgICBzcGxpdC5ieSA9ICdDZWxsX1R5cGUyJykgKyBSb3RhdGVkQXhpcygpCiMgYWxsIHRoZSBleHByZXNzaW9uIGxldmVscyBhcmUgbG93ZXIgaW4gcmVndWxhciBuZXVyb25zIHRoYW4gREEgbmV1cm9ucwoKRG90UGxvdChhbGwubmV1cm9ucywgZ3JvdXAuYnkgPSAnb3JpZy5pZGVudCcsIGZlYXR1cmVzID0gcmVndWxhdGUuZ2VuZXMpICsgUm90YXRlZEF4aXMoKQoKIyB1cCByZWcgaW4gTmV1cm9uczIKIyBtYW55IE1UIGdlbmUsIGFsc28gIkZUSDEiLCJGVEwiLCJBUE9FIiwiU0FUMSIsIlBUTiIsIkdBQkFSQVAiLCJQVEdEUyIKCiMgdG9wIHVwIHJlZyBnZW5lcyBpbiBOZXVyb25zMgojIk1BTEFUMSIgICJNVC1ORDIiICAiTVQtQ08xIiAgIk1ULUNPMiIgICJNVC1BVFA2IiAiTVQtQ08zIiAgIk1ULU5EMyIgICJNVC1DWUIiIAoKcmVndWxhdGUuZ2VuZXMgPC0gYygiRlRIMSIsIkZUTCIsIkFQT0UiLCJTQVQxIiwiUFROIiwiR0FCQVJBUCIsIlBUR0RTIiwiU1BBUkNMMSIsCiAgICAgICAgICAgICAgICAgICAgIlJQTDE3IiwiTVRSTlIyTDEyIiwiTVRSTlIyTDgiLCJTTkhHMjUiLCJTRUxFTk9XIiwKICAgICAgICAgICAgICAgICAgICAiQ1JZQUIiLCAiUEVBMTUiLCAiQVRQMUEyIiwgIlNFTEVOT0siLCJJR0ZCUDciLCAiUkFCM0IiKQojIHN0cm9uZ2x5IGFsdGVyZWQgZ2VuZXMKcmVndWxhdGUuZ2VuZXMgPC0gYygiRlRIMSIsIkZUTCIsIlBUTiIsIlBUR0RTIiwiU1BBUkNMMSIsCiAgICAgICAgICAgICAgICAgICAgIlNFTEVOT1ciLCJDUllBQiIsICJNQUxBVDEiLCAiTVQtTkQyIiwgIk1ULUNPMSIsICJNVC1DTzIiLAogICAgICAgICAgICAgICAgICAgICJNVC1BVFA2IiwgIk1ULUNPMyIsICJNVC1ORDMiLCAiTVQtQ1lCIikKcmVndWxhdGUuZ2VuZXMgPC0gYygiTVQtTkQyIiwgIk1ULUNPMSIsICJNVC1DTzIiLAogICAgICAgICAgICAgICAgICAgICJNVC1BVFA2IiwgIk1ULUNPMyIsICJNVC1ORDMiLAogICAgICAgICAgICAgICAgICAgICJGVEgxIiwiRlRMIiwKICAgICAgICAgICAgICAgICAgICAiQ1JZQUIiKQoKIyBnZW5lcyB1cCBhbmQgZG93biAKcmVndWxhdGUuZ2VuZXMgPC0gYygiRlpEMyIsIkFTQ0wxIiwiU09YNCIsCiAgICAgICAgICAgICAgICAgICAgIlRDRjQiLCJDQUxSIiwiUEFYNiIsIAogICAgICAgICAgICAgICAgICAgICJDRDI0IiwiS0NOUTFPVDEiLCJDQ05HMiIsIk1ULU5EMiIsICJNVC1DTzEiLCAiTVQtQ08yIiwKICAgICAgICAgICAgICAgICAgICAiTVQtQVRQNiIsICJNVC1DTzMiLCAiTVQtTkQzIiwKICAgICAgICAgICAgICAgICAgICAiRlRIMSIsIkZUTCIsCiAgICAgICAgICAgICAgICAgICAgIkNSWUFCIikKCkRvdFBsb3QoYWxsLm5ldXJvbnMsIGdyb3VwLmJ5ID0gJ29yaWcuaWRlbnQnLCBmZWF0dXJlcyA9IHJlZ3VsYXRlLmdlbmVzKSArIFJvdGF0ZWRBeGlzKCkKCnBkZihwYXN0ZShvdXRwdXRfcGF0aCwiRG90UGxvdERFR19OMXZzTjIucGRmIikpCkRvdFBsb3QoYWxsLm5ldXJvbnMsIGdyb3VwLmJ5ID0gJ29yaWcuaWRlbnQnLCBmZWF0dXJlcyA9IHJlZ3VsYXRlLmdlbmVzKSArIFJvdGF0ZWRBeGlzKCkKZGV2Lm9mZigpCgoKYGBgCgoKCgoKCgoKCmBgYHtyfQpCaW9jTWFuYWdlcjo6aW5zdGFsbCgiY2x1c3RlclByb2ZpbGVyIikKQmlvY01hbmFnZXI6Omluc3RhbGwoInBhdGh2aWV3IikKQmlvY01hbmFnZXI6Omluc3RhbGwoImVucmljaHBsb3QiKQpsaWJyYXJ5KGNsdXN0ZXJQcm9maWxlcikKbGlicmFyeShlbnJpY2hwbG90KQojIHdlIHVzZSBnZ3Bsb3QyIHRvIGFkZCB4IGF4aXMgbGFiZWxzIChleDogcmlkZ2VwbG90KQpsaWJyYXJ5KGdncGxvdDIpCmBgYAoKCgpUcnkgd2l0aCBjbHVzdGVyIHByb2ZpbGVyCgpgYGB7cn0KCiMgbmVlZCBhIGdlbmUgbGlzdCBzb3J0ZWQgaW4gZGVjcmVhc2luZyBvcmRlcgojIGdldCB0aGUgbG9nMkZDCm9yaWdpbmFsX2dlbmVfbGlzdCA8LSBkZWcubmV1cm9ucyRhdmdfbG9nMkZDCiMgbmFtZSB0aGUgdmVjdG9yIC0gYWRkIHRoZSBnZW5lIG5hbWVzCm5hbWVzKG9yaWdpbmFsX2dlbmVfbGlzdCkgPC0gcm93bmFtZXMoZGVnLm5ldXJvbnMpCmdlbmVfbGlzdCA9IG5hLm9taXQob3JpZ2luYWxfZ2VuZV9saXN0KQoKZ2VuZV9saXN0ID0gc29ydChnZW5lX2xpc3QsIGRlY3JlYXNpbmcgPSBUUlVFKQoKIyBnZXQgdGhlIGdlbmUgc2V0IGVucmljaG1lbnQgbGlzdApsaWJyYXJ5KG9yZy5Icy5lZy5kYikKCmdzZSA8LSBnc2VHTyhnZW5lTGlzdD1nZW5lX2xpc3QsIAogICAgICAgICAgICAgb250ID0iQlAiLCAKICAgICAgICAgICAgIGtleVR5cGUgPSAiU1lNQk9MIiwgCiAgICAgICAgICAgICBtaW5HU1NpemUgPSAzLCAKICAgICAgICAgICAgIG1heEdTU2l6ZSA9IDgwMCwgCiAgICAgICAgICAgICBwdmFsdWVDdXRvZmYgPSAwLjA1LCAKICAgICAgICAgICAgIHZlcmJvc2UgPSBUUlVFLCAKICAgICAgICAgICAgIE9yZ0RiID0gb3JnLkhzLmVnLmRiLCAKICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAibm9uZSIpCgpyZXF1aXJlKERPU0UpCmRvdHBsb3QoZ3NlLCBzaG93Q2F0ZWdvcnk9MjAsIHNwbGl0PSIuc2lnbiIpICsgZmFjZXRfZ3JpZCgufi5zaWduKQoKZW1hcHBsb3QoZ3NlLCBzaG93Q2F0ZWdvcnkgPSAxMCkKCmBgYAoKClByZWRpY3QgY2VsbCB0eXBlcyBhZ2FpbiB0byBtYWtlIHRhYmxlIDEyCk9yZ2Fub2lkcyBpbiBob3VzZSBkYXRhCgpgYGB7cn0KCnBhdGh3YXkgPC0gIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0RvY3VtZW50cy9EYXRhL3NjUk5Bc2VxL1BoZW5vSUQvc2NSTkFzZXFTb3J0ZWQvb2Jqcy8iCnNldS5zYyA8LSByZWFkUkRTKHBhc3RlKHBhdGh3YXksICJDb21iaW5lZExhYmVsZWRNYXJrZXJzMTQxMDIwMjIuUkRTIikpCgojIHByZWRpY3Qgd2l0aCBBSVcKIyBTTkNBIGFuZCBjb250cm9sIG1pZGJyYWluIG9yZ2Fub2lkcyAxNjUgZGF5cyBpbiBjdWx0dXJlCkFTVDIzIDwtIHJlYWRSRFMoIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0RvY3VtZW50cy9EYXRhL3NjUk5Bc2VxL0FTVDIzX0JyYWluQ29tbS9NQk9jbHVzdGVyc19uYW1lczI5MDcyMDIxLnJkcyIpCgojIE1pZGJyYWluICBBSVcwMDIgMTIwIGRheXMgaW4gY3VsdHVyZQpBSVcxMjAgPC0gcmVhZFJEUygiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL0RhdGEvc2NSTkFzZXEvQUlXdHJpbzEyMGRheXMvTU9pbnRlZ3JhdGVkQ2x1c3RlcksxMjNyZXMwLjgubmFtZXNfbm92MTZfMjAyMSIpCgojIE1pZGJyYWluIEFJVzAwMiA2MCBkYXlzIGluIGN1bHR1cmUKCkFJVzYwIDwtIHJlYWRSRFMoIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0RvY3VtZW50cy9EYXRhL3NjUk5Bc2VxL0FJV3RyaW82MGRheXMvQVdJMDAyUGFya2luS09QaW5rS082MGRheXNfbGFiZWxzXzE0MDUyMDIyLnJkcyIpCgoKIyBBU1QyMwpzZXUuciA8LSBBU1QyMwpzZXUucSA8LSBzZXUuc2MKCmFuY2hvcnMgPC0gRmluZFRyYW5zZmVyQW5jaG9ycyhyZWZlcmVuY2UgPSBzZXUuciwgcXVlcnkgPSBzZXUucSwgZGltcyA9IDE6MjUpCnByaW50KCJnZXR0aW5nIHByZWRpY3Rpb25zIikKcHJlZGljdGlvbnMgPC0gVHJhbnNmZXJEYXRhKGFuY2hvcnNldCA9IGFuY2hvcnMsIHJlZmRhdGEgPSBzZXUuciRjbHVzdGVyX2xhYmVscywgay53ZWlnaHQgPSA1MCkKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3RlZC5pZCwgY29sLm5hbWUgPSAicHJlZGljdGlvbiIpCnNldS5xIDwtIEFkZE1ldGFEYXRhKHNldS5xLCBwcmVkaWN0aW9ucyRwcmVkaWN0aW9uLnNjb3JlLm1heCwgY29sLm5hbWUgPSAicHJlZGljdGlvbi5zY29yZS5tYXgiKQoKCnNldS5xJEFTVDIzLnByZWQgPC0gaWZlbHNlKHNldS5xJHByZWRpY3Rpb24uc2NvcmUubWF4ID4gMC40LCBzZXUucSRwcmVkaWN0aW9uLCAibm9uZSIpCgpEaW1QbG90KHNldS5xLCBncm91cC5ieSA9ICdBU1QyMy5wcmVkJykKCiMgQUlXIDYwCnNldS5yIDwtIEFJVzYwCmNvbG5hbWVzKHNldS5yQG1ldGEuZGF0YSkKCmFuY2hvcnMgPC0gRmluZFRyYW5zZmVyQW5jaG9ycyhyZWZlcmVuY2UgPSBzZXUuciwgcXVlcnkgPSBzZXUucSwgZGltcyA9IDE6MjUpCnByaW50KCJnZXR0aW5nIHByZWRpY3Rpb25zIikKcHJlZGljdGlvbnMgPC0gVHJhbnNmZXJEYXRhKGFuY2hvcnNldCA9IGFuY2hvcnMsIHJlZmRhdGEgPSBzZXUuciRjbHVzdGVyLmlkcywgay53ZWlnaHQgPSA1MCkKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3RlZC5pZCwgY29sLm5hbWUgPSAicHJlZGljdGlvbiIpCnNldS5xIDwtIEFkZE1ldGFEYXRhKHNldS5xLCBwcmVkaWN0aW9ucyRwcmVkaWN0aW9uLnNjb3JlLm1heCwgY29sLm5hbWUgPSAicHJlZGljdGlvbi5zY29yZS5tYXgiKQoKCnNldS5xJEFJVzYwLnByZWQgPC0gaWZlbHNlKHNldS5xJHByZWRpY3Rpb24uc2NvcmUubWF4ID4gMC40LCBzZXUucSRwcmVkaWN0aW9uLCAibm9uZSIpCkRpbVBsb3Qoc2V1LnEsIGdyb3VwLmJ5ID0gJ0FJVzYwLnByZWQnKQoKCiMgQUlXIDEyMApzZXUuciA8LSBBSVcxMjAKY29sbmFtZXMoc2V1LnJAbWV0YS5kYXRhKQoKYW5jaG9ycyA8LSBGaW5kVHJhbnNmZXJBbmNob3JzKHJlZmVyZW5jZSA9IHNldS5yLCBxdWVyeSA9IHNldS5xLCBkaW1zID0gMToyNSkKcHJpbnQoImdldHRpbmcgcHJlZGljdGlvbnMiKQpwcmVkaWN0aW9ucyA8LSBUcmFuc2ZlckRhdGEoYW5jaG9yc2V0ID0gYW5jaG9ycywgcmVmZGF0YSA9IHNldS5yJHJlczA4bmFtZXMyLCBrLndlaWdodCA9IDUwKQpzZXUucSA8LSBBZGRNZXRhRGF0YShzZXUucSwgcHJlZGljdGlvbnMkcHJlZGljdGVkLmlkLCBjb2wubmFtZSA9ICJwcmVkaWN0aW9uIikKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3Rpb24uc2NvcmUubWF4LCBjb2wubmFtZSA9ICJwcmVkaWN0aW9uLnNjb3JlLm1heCIpCgoKc2V1LnEkQUlXMTIwLnByZWQgPC0gaWZlbHNlKHNldS5xJHByZWRpY3Rpb24uc2NvcmUubWF4ID4gMC44LCBzZXUucSRwcmVkaWN0aW9uLCAibm9uZSIpCkRpbVBsb3Qoc2V1LnEsIGdyb3VwLmJ5ID0gJ0FJVzEyMC5wcmVkJykKCgoKYGBgCgoKTW9yZSBwcmVkaWN0aW9ucyAKRGV2ZWxvcGluZyBicmFpbjogQ29ydGV4CiAgICAgICAgICAgICAgICAgIEZvcmVicmFpbgoKQWR1bHQgYnJhaW46IHdob2xlIGJyYWluIHdpdGggc3VidHlwZXMKQWR1bHQgYnJhaW4gbWlkYnJhaW4gYW5kIHN0cmlhdHVtCkFkdWx0IGJyYWluIG1pZGJyYWluIG1haW4gY2VsbCB0eXBlcwpBZHVsdCBicmFpbiBEQSBvciBBc3RybyBzdWJ0eXBlcwoKCmBgYHtyfQoKCkRBc3VidHlwZXMgPC0gcmVhZFJEUygiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL0RhdGEvc2NSTkFzZXEvTWFjb3Nrb19EYXRhL0RBc3ViZ3JvdXBzX3Byb2Nlc3NlZC5SZHMiKQoKCnNldS5yIDwtIERBc3VidHlwZXMKY29sbmFtZXMoc2V1LnJAbWV0YS5kYXRhKQoKYW5jaG9ycyA8LSBGaW5kVHJhbnNmZXJBbmNob3JzKHJlZmVyZW5jZSA9IHNldS5yLCBxdWVyeSA9IHNldS5xLCBkaW1zID0gMToyNSkKcHJpbnQoImdldHRpbmcgcHJlZGljdGlvbnMiKQpwcmVkaWN0aW9ucyA8LSBUcmFuc2ZlckRhdGEoYW5jaG9yc2V0ID0gYW5jaG9ycywgcmVmZGF0YSA9IHNldS5yJENlbGxfU3VidHlwZSwgay53ZWlnaHQgPSAyMCkKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3RlZC5pZCwgY29sLm5hbWUgPSAicHJlZGljdGlvbiIpCnNldS5xIDwtIEFkZE1ldGFEYXRhKHNldS5xLCBwcmVkaWN0aW9ucyRwcmVkaWN0aW9uLnNjb3JlLm1heCwgY29sLm5hbWUgPSAicHJlZGljdGlvbi5zY29yZS5tYXgiKQoKCnNldS5xJERBc3ViLnByZWQgPC0gaWZlbHNlKHNldS5xJHByZWRpY3Rpb24uc2NvcmUubWF4ID4gMC40LCBzZXUucSRwcmVkaWN0aW9uLCAibm9uZSIpCkRpbVBsb3Qoc2V1LnEsIGdyb3VwLmJ5ID0gJ0RBc3ViLnByZWQnKQoKCiMgYXN0cm9jeXRlcwoKYXN0cm8ucmVmIDwtIHJlYWRSRFMoIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0RvY3VtZW50cy9EYXRhL3NjUk5Bc2VxL01hY29za29fRGF0YS9QRF9hc3Ryby5SZHMiKQojIG5lZWQgdG8gbWFrZSBQQ0EgYW5kIFVNQVAKYXN0cm8ucmVmIDwtIE5vcm1hbGl6ZURhdGEoYXN0cm8ucmVmKQphc3Ryby5yZWYgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoYXN0cm8ucmVmLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCmFzdHJvLnJlZiA8LSBTY2FsZURhdGEoYXN0cm8ucmVmKQphc3Ryby5yZWYgPC0gUnVuUENBKGFzdHJvLnJlZikKYXN0cm8ucmVmIDwtIFJ1blVNQVAoYXN0cm8ucmVmLCByZWR1Y3Rpb24gPSAicGNhIiwgbi5uZWlnaGJvcnMgPSAyMDUsIGRpbXMgPSAxOjI1KQoKCnNldS5yIDwtIGFzdHJvLnJlZgoKYW5jaG9ycyA8LSBGaW5kVHJhbnNmZXJBbmNob3JzKHJlZmVyZW5jZSA9IHNldS5yLCBxdWVyeSA9IHNldS5xLCBkaW1zID0gMToyNSkKcHJpbnQoImdldHRpbmcgcHJlZGljdGlvbnMiKQpwcmVkaWN0aW9ucyA8LSBUcmFuc2ZlckRhdGEoYW5jaG9yc2V0ID0gYW5jaG9ycywgcmVmZGF0YSA9IHNldS5yJENlbGxfU3VidHlwZSwgay53ZWlnaHQgPSAyNSkKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3RlZC5pZCwgY29sLm5hbWUgPSAicHJlZGljdGlvbiIpCnNldS5xIDwtIEFkZE1ldGFEYXRhKHNldS5xLCBwcmVkaWN0aW9ucyRwcmVkaWN0aW9uLnNjb3JlLm1heCwgY29sLm5hbWUgPSAicHJlZGljdGlvbi5zY29yZS5tYXgiKQpzZXUucSRBc3Ryby5zdWIgPC0gaWZlbHNlKHNldS5xJHByZWRpY3Rpb24uc2NvcmUubWF4ID4gMC44LCBzZXUucSRwcmVkaWN0aW9uLCAibm9uZSIpCkRpbVBsb3Qoc2V1LnEsIGdyb3VwLmJ5ID0gJ0FzdHJvLnN1YicpCgoKIyBNaWRicmFpbiBhbmQgU3RyaWF0dW0gCgpzZXUuciA8LSByZWFkUkRTKCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb2N1bWVudHMvRGF0YS9zY1JOQXNlcS9QdWJsaWNEYXRhL0JoYWR1cmlfbWlkYnJhaW5fc3RyaWF0dW0uUkRTIikKCiMgd2hvbGUgYnJhaW4Kc2V1LnIgPC0gcmVhZFJEUygiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL0RhdGEvc2NSTkFzZXEvUHVibGljRGF0YS9CaGFkdXJpX2Rvd25zYW1wbGUuUkRTIikKCgpJZGVudHMoc2V1LnIpIDwtICJjZWxsX2NsdXN0ZXIiCgojIGZpbmQgdGhlIHJlZmVyZW5jZSBhbmNob3JzCmFuY2hvcnMgPC0gRmluZFRyYW5zZmVyQW5jaG9ycyhyZWZlcmVuY2UgPSBzZXUuciwgcXVlcnkgPSBzZXUucSwgZGltcyA9IDE6MjUpCnByZWRpY3Rpb25zIDwtIFRyYW5zZmVyRGF0YShhbmNob3JzZXQgPSBhbmNob3JzLCByZWZkYXRhID0gc2V1LnIkY2VsbF9jbHVzdGVyLCBrLndlaWdodCA9IDI1KQpzZXUucSA8LSBBZGRNZXRhRGF0YShzZXUucSwgcHJlZGljdGlvbnMkcHJlZGljdGVkLmlkLCBjb2wubmFtZSA9ICJwcmVkaWN0aW9uIikKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3Rpb24uc2NvcmUubWF4LCBjb2wubmFtZSA9ICJwcmVkaWN0aW9uLnNjb3JlLm1heCIpCnNldS5xJEJyYWluIDwtIGlmZWxzZShzZXUucSRwcmVkaWN0aW9uLnNjb3JlLm1heCA+IDAuMywgc2V1LnEkcHJlZGljdGlvbiwgIm5vbmUiKQpEaW1QbG90KHNldS5xLCBncm91cC5ieSA9ICdCcmFpbicpCgoKIyBkZXZlbG9waW5nIGZvcmVicmFpbgoKc2V1LnIgPC0gcmVhZFJEUygiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL0RhdGEvc2NSTkFzZXEvUHVibGljRGF0YS9LYXJvbGluc2tpX0RldkZvcmVicmFpbl9kb3duc2FtcGxlX0xldmVsMS5SRFMiKQpjb2xuYW1lcyhzZXUuckBtZXRhLmRhdGEpCklkZW50cyhzZXUucikgPC0gJ0NsdXN0ZXJzJwoKYW5jaG9ycyA8LSBGaW5kVHJhbnNmZXJBbmNob3JzKHJlZmVyZW5jZSA9IHNldS5yLCBxdWVyeSA9IHNldS5xLCBkaW1zID0gMToyNSkKcHJlZGljdGlvbnMgPC0gVHJhbnNmZXJEYXRhKGFuY2hvcnNldCA9IGFuY2hvcnMsIHJlZmRhdGEgPSBzZXUuciRDbHVzdGVycywgay53ZWlnaHQgPSAyNSkKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3RlZC5pZCwgY29sLm5hbWUgPSAicHJlZGljdGlvbiIpCnNldS5xIDwtIEFkZE1ldGFEYXRhKHNldS5xLCBwcmVkaWN0aW9ucyRwcmVkaWN0aW9uLnNjb3JlLm1heCwgY29sLm5hbWUgPSAicHJlZGljdGlvbi5zY29yZS5tYXgiKQpzZXUucSRkZXZGb3JlYnJhaW4gPC0gaWZlbHNlKHNldS5xJHByZWRpY3Rpb24uc2NvcmUubWF4ID4gMC41LCBzZXUucSRwcmVkaWN0aW9uLCAibm9uZSIpCkRpbVBsb3Qoc2V1LnEsIGdyb3VwLmJ5ID0gJ2RldkZvcmVicmFpbicpCgojIGRldmVsb3BpbmcgZm9yZWJyYWluCnNldS5yIDwtIHJlYWRSRFMoIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0RvY3VtZW50cy9EYXRhL3NjUk5Bc2VxL1B1YmxpY0RhdGEvTm93YWtvd3NraV9kZXZfY29ydGV4dC5SRFMiKQoKY29sbmFtZXMoc2V1LnJAbWV0YS5kYXRhKQpJZGVudHMoc2V1LnIpIDwtICdXR0NOQWNsdXN0ZXInCgphbmNob3JzIDwtIEZpbmRUcmFuc2ZlckFuY2hvcnMocmVmZXJlbmNlID0gc2V1LnIsIHF1ZXJ5ID0gc2V1LnEsIGRpbXMgPSAxOjI1KQpwcmVkaWN0aW9ucyA8LSBUcmFuc2ZlckRhdGEoYW5jaG9yc2V0ID0gYW5jaG9ycywgcmVmZGF0YSA9IHNldS5yJFdHQ05BY2x1c3Rlciwgay53ZWlnaHQgPSAyNSkKc2V1LnEgPC0gQWRkTWV0YURhdGEoc2V1LnEsIHByZWRpY3Rpb25zJHByZWRpY3RlZC5pZCwgY29sLm5hbWUgPSAicHJlZGljdGlvbiIpCnNldS5xIDwtIEFkZE1ldGFEYXRhKHNldS5xLCBwcmVkaWN0aW9ucyRwcmVkaWN0aW9uLnNjb3JlLm1heCwgY29sLm5hbWUgPSAicHJlZGljdGlvbi5zY29yZS5tYXgiKQpzZXUucSRkZXZjb3J0ZXggPC0gaWZlbHNlKHNldS5xJHByZWRpY3Rpb24uc2NvcmUubWF4ID4gMC4zLCBzZXUucSRwcmVkaWN0aW9uLCAibm9uZSIpCkRpbVBsb3Qoc2V1LnEsIGdyb3VwLmJ5ID0gJ2RldmNvcnRleCcpCgpgYGAKCgoKClRhYmxlcyBvZiB0b3AgcHJlZGljdGlvbnMgCgpgYGB7cn0KI0FTVDIzCnQubGFibGVzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoc2V1LnEkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsc2V1LnEkQVNUMjMucHJlZCkpCnQubGFibGVzJEZyZXEgPC0gYXMuZG91YmxlKHQubGFibGVzJEZyZXEpCgoKI0FJVyA2MAoKdC5sYWJsZXMgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShzZXUucSRDZWxsX1N1YnR5cGVfTWFya2VycyxzZXUucSRBSVc2MC5wcmVkKSkKdC5sYWJsZXMkRnJlcSA8LSBhcy5kb3VibGUodC5sYWJsZXMkRnJlcSkKCgoKIyBBSVcgMTIwCnQubGFibGVzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoc2V1LnEkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsc2V1LnEkQUlXMTIwLnByZWQpKQp0LmxhYmxlcyRGcmVxIDwtIGFzLmRvdWJsZSh0LmxhYmxlcyRGcmVxKQoKCgojIERBIG5ldXJvbiBzdWJ0eXBlIHByZWRpY3Rpb25zCnQubGFibGVzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoc2V1LnEkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsc2V1LnEkREFzdWIucHJlZCkpCnQubGFibGVzJEZyZXEgPC0gYXMuZG91YmxlKHQubGFibGVzJEZyZXEpCgoKIyBBc3RybyBzdWJ0eXBlCnQubGFibGVzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoc2V1LnEkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsc2V1LnEkQXN0cm8uc3ViKSkKdC5sYWJsZXMkRnJlcSA8LSBhcy5kb3VibGUodC5sYWJsZXMkRnJlcSkKCiMgTWlkYnJhaW4gQmhhZHVuaSBwcmVkaWN0aW9ucwp0LmxhYmxlcyA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKHNldS5xJENlbGxfU3VidHlwZV9NYXJrZXJzLHNldS5xJE1pZGJyYWluKSkKdC5sYWJsZXMkRnJlcSA8LSBhcy5kb3VibGUodC5sYWJsZXMkRnJlcSkKCiMgd2hvbGUgYnJhaW4KdC5sYWJsZXMgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShzZXUucSRDZWxsX1N1YnR5cGVfTWFya2VycyxzZXUucSRCcmFpbikpCnQubGFibGVzJEZyZXEgPC0gYXMuZG91YmxlKHQubGFibGVzJEZyZXEpCgojIGRldmVsb3BpbmcgZm9yZWJyYWluCnQubGFibGVzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoc2V1LnEkQ2VsbF9TdWJ0eXBlX01hcmtlcnMsc2V1LnEkZGV2Rm9yZWJyYWluKSkKdC5sYWJsZXMkRnJlcSA8LSBhcy5kb3VibGUodC5sYWJsZXMkRnJlcSkKCiMgZGV2ZWxvcGluZyBjb3J0ZXgKdC5sYWJsZXMgPC0gYXMuZGF0YS5mcmFtZSh0YWJsZShzZXUucSRDZWxsX1N1YnR5cGVfTWFya2VycyxzZXUucSRkZXZjb3J0ZXgpKQp0LmxhYmxlcyRGcmVxIDwtIGFzLmRvdWJsZSh0LmxhYmxlcyRGcmVxKQoKdG9wLnByZWRpY3Rpb24gPC1hcy5kYXRhLmZyYW1lKHQubGFibGVzICAlPiUgZ3JvdXBfYnkoVmFyMSkgICU+JSB0b3BfbigxLCBGcmVxKSkKdG9wLnByZWRpY3Rpb24KCgoKCmBgYAoKCgoKCgo=